GOF23設計模式之責任鏈模式(chain of responsibility)

1、責任鏈模式概述

  將可以處理同一類請求的對象連成一條鏈,所提交的請求沿着鏈傳遞,鏈上的對象逐個判斷是否有能力處理該請求。數組

  若是能則處理,不然傳遞給鏈上的下一個對象去處理。ide

  定義責任鏈測試

    (1)經過鏈表的方式實現職責鏈this

    (2)經過非鏈表的方式實現職責鏈spa

        經過集合、數組生成職責鏈更加實用!實際上,不少項目中,每一個具體的Handler並非由開發團隊定義的,而是項目上線後由外部單位追加的,因此使用鏈表方式定義責任鏈(COR)就很困難!code

2、責任鏈模式場景

  (1)公司裏面,請假條審批過程:對象

      ① 若是請假天數小於3天,主任審批blog

      ② 若是請假天數大於等於3天,小於10天,經理審批事件

      ③ 若是請假天數大於等於10天,小於30天,總經理審批ip

      ④ 若是請假天數大於等於30天,提示拒絕

  (2)添加新的處理對象:

      能夠在流程中增長新的「副總經理」角色,審批大於等於10天,小於20天的狀況。

      ① 若是請假天數小於3天,主任審批

      ② 若是請假天數大於等於3天,小於10天,經理審批

      ③【增長】若是請假天數大於等於10天,小於20天,副總經理審批

      ④ 若是請假天數大於等於20天,小於30天,總經理審批

      ⑤ 若是請假天數大於等於30天,提示拒絕

3、使用責任鏈模式模擬公司請假流程

 1 /**
 2  * 封裝請假的基本信息
 3  * @author CL
 4  *
 5  */
 6 public class LeaveRequest {
 7     /**
 8      * 員工姓名
 9      */
10     private String empName;
11     /**
12      * 請假天數
13      */
14     private int leaveDays;
15     /**
16      * 請假事由 
17      */
18     private String reason;
19     
20     public LeaveRequest() {
21     }
22 
23     public LeaveRequest(String empName, int leaveDays, String reason) {
24         this.empName = empName;
25         this.leaveDays = leaveDays;
26         this.reason = reason;
27     }
28 
29     public String getEmpName() {
30         return empName;
31     }
32 
33     public void setEmpName(String empName) {
34         this.empName = empName;
35     }
36 
37     public int getLeaveDays() {
38         return leaveDays;
39     }
40 
41     public void setLeaveDays(int leaveDays) {
42         this.leaveDays = leaveDays;
43     }
44 
45     public String getReason() {
46         return reason;
47     }
48 
49     public void setReason(String reason) {
50         this.reason = reason;
51     }
52     
53 }
 1 /**
 2  * 抽象類(領導)
 3  * @author CL
 4  *
 5  */
 6 public abstract class Leader {
 7     protected String name;
 8     /**
 9      * 責任鏈上的後繼對象
10      */
11     protected Leader nextLeader;
12 
13     public Leader(String name) {
14         this.name = name;
15     }
16 
17     /**
18      * 設定責任鏈上的後即對象
19      * @param nextLeader
20      */
21     public void setNextLeader(Leader nextLeader) {
22         this.nextLeader = nextLeader;
23     }
24     
25     /**
26      * 處理請假請求的核心業務方法
27      * @param leaveRequest
28      */
29     public abstract void handlerRequest(LeaveRequest leaveRequest);
30     
31     
32 }
 1 /**
 2  * 主任
 3  * @author CL
 4  *
 5  */
 6 public class Director extends Leader {
 7 
 8     public Director(String name) {
 9         super(name);
10     }
11 
12     @Override
13     public void handlerRequest(LeaveRequest leaveRequest) {
14         if (leaveRequest.getLeaveDays() < 3) {
15             System.out.println("員工:"+leaveRequest.getEmpName()+",請假:"
16                     +leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
17             System.out.println("主任:"+this.name+",審批經過!");
18         } else {    //責任鏈上的後繼對象處理
19             if (this.nextLeader != null) {
20                 this.nextLeader.handlerRequest(leaveRequest);
21             }
22         }
23     }
24 
25 }
 1 /**
 2  * 經理
 3  * @author CL
 4  *
 5  */
 6 public class Manager extends Leader {
 7 
 8     public Manager(String name) {
 9         super(name);
10     }
11 
12     @Override
13     public void handlerRequest(LeaveRequest leaveRequest) {
14         if (leaveRequest.getLeaveDays() < 10) {
15             System.out.println("員工:"+leaveRequest.getEmpName()+",請假:"
16                     +leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
17             System.out.println("經理:"+this.name+",審批經過!");
18         } else {    //責任鏈上的後繼對象處理
19             if (this.nextLeader != null) {
20                 this.nextLeader.handlerRequest(leaveRequest);
21             }
22         }
23     }
24 
25 }
 1 /**
 2  * 副總經理
 3  * @author CL
 4  *
 5  */
 6 public class ViceGeneraManager extends Leader {
 7 
 8     public ViceGeneraManager(String name) {
 9         super(name);
10     }
11 
12     @Override
13     public void handlerRequest(LeaveRequest leaveRequest) {
14         if (leaveRequest.getLeaveDays() < 20) {
15             System.out.println("員工:"+leaveRequest.getEmpName()+",請假:"
16                     +leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
17             System.out.println("副總經理:"+this.name+",審批經過!");
18         } else {    //責任鏈上的後繼對象處理
19             if (this.nextLeader != null) {
20                 this.nextLeader.handlerRequest(leaveRequest);
21             }
22         }
23     }
24 
25 }
 1 /**
 2  * 總經理
 3  * @author CL
 4  *
 5  */
 6 public class GeneraManager extends Leader {
 7 
 8     public GeneraManager(String name) {
 9         super(name);
10     }
11 
12     @Override
13     public void handlerRequest(LeaveRequest leaveRequest) {
14         if (leaveRequest.getLeaveDays() < 30) {
15             System.out.println("總經理:"+leaveRequest.getEmpName()+",請假:"
16                     +leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
17             System.out.println("主任:"+this.name+",審批經過!");
18         } else {    //無責任鏈上的後繼對象
19             System.out.println("員工:"+leaveRequest.getEmpName()+",請假天數:"
20                     +leaveRequest.getLeaveDays()+"天,超過30天,不予請假!");
21         }
22     }
23 
24 }

  測試:

 1 /**
 2  * 測試責任鏈模式
 3  * @author CL
 4  *
 5  */
 6 public class Client {
 7 
 8     public static void main(String[] args) {
 9         Leader a = new Director("張主任");
10         Leader b = new Manager("李經理");
11         Leader c = new ViceGeneraManager("王副總經理");
12         Leader d = new GeneraManager("趙總經理");
13         
14         //構建責任鏈
15         a.setNextLeader(b);
16         b.setNextLeader(c);
17         c.setNextLeader(d);
18         
19         //請假
20         LeaveRequest req1 = new LeaveRequest("Tom", 2, "生病"); 
21         LeaveRequest req2 = new LeaveRequest("Jame", 15, "回家"); 
22         LeaveRequest req3 = new LeaveRequest("Rose", 25, "調休"); 
23         LeaveRequest req4 = new LeaveRequest("Jack", 35, "鬧着玩"); 
24         
25         //審批
26         a.handlerRequest(req1);
27         a.handlerRequest(req2);
28         a.handlerRequest(req3);
29         a.handlerRequest(req4);
30     }
31 }

  控制檯輸出:

員工:Tom,請假:2天,理由:生病
主任:張主任,審批經過!
員工:Jame,請假:15天,理由:回家
副總經理:王副總經理,審批經過!
總經理:Rose,請假:25天,理由:調休
主任:趙總經理,審批經過!
員工:Jack,請假天數:35天,超過30天,不予請假!

4、責任鏈模式常見開發應用場景

  (1)Java 中,異常處理機制就是一種責任鏈模式。一個 try 能夠對應多個 catch,當第一個 catch 不匹配類型,則自動跳到第二個 catch;

  (2)JavaScript 語言中,事件的冒泡和捕獲機制(Java 語言中事件的處理採用觀察者模式);

  (3)Servlet 開發中,過濾器的鏈式處理;

  (4)Struts2 中,攔截器的調用也是典型的責任鏈模式;

  (5)…………

相關文章
相關標籤/搜索