GOF23设计模式之责任链模式(chain of responsibility)

一、责任链模式概述

  将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求。

  如果能则处理,否则传递给链上的下一个对象去处理。

  定义责任链

    (1)通过链表的方式实现职责链

    (2)通过非链表的方式实现职责链

        通过集合、数组生成职责链更加实用!实际上,很多项目中,每个具体的Handler并不是由开发团队定义的,而是项目上线后由外部单位追加的,所以使用链表方式定义责任链(COR)就很困难!

二、责任链模式场景

  (1)公司里面,请假条审批过程:

      ① 如果请假天数小于3天,主任审批

      ② 如果请假天数大于等于3天,小于10天,经理审批

      ③ 如果请假天数大于等于10天,小于30天,总经理审批

      ④ 如果请假天数大于等于30天,提示拒绝

  (2)添加新的处理对象:

      可以在流程中增加新的“副总经理”角色,审批大于等于10天,小于20天的情况。

      ① 如果请假天数小于3天,主任审批

      ② 如果请假天数大于等于3天,小于10天,经理审批

      ③【增加】如果请假天数大于等于10天,小于20天,副总经理审批

      ④ 如果请假天数大于等于20天,小于30天,总经理审批

      ⑤ 如果请假天数大于等于30天,提示拒绝

三、使用责任链模式模拟公司请假流程

 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天,不予请假!

四、责任链模式常见开发应用场景

  (1)Java 中,异常处理机制就是一种责任链模式。一个 try 可以对应多个 catch,当第一个 catch 不匹配类型,则自动跳到第二个 catch;

  (2)JavaScript 语言中,事件的冒泡和捕获机制(Java 语言中事件的处理采用观察者模式);

  (3)Servlet 开发中,过滤器的链式处理;

  (4)Struts2 中,拦截器的调用也是典型的责任链模式;

  (5)…………

原文地址:https://www.cnblogs.com/cao-lei/p/8328160.html