zoukankan      html  css  js  c++  java
  • 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)…………

  • 相关阅读:
    Windwos堆管理体系以及溢出利用
    Python利用ctypes实现C库函数调用
    Windows异常分发
    初探Windows用户态调试机制
    HTTP协议
    《格蠹汇编》调试笔记
    IDT系统中断描述表以及绕过Xurtr检测的HOOK姿势
    C++ 各种构造函数
    PsSetCreateProcessNotifyRoutineEx 创建回调函数
    导出函数与未导出函数
  • 原文地址:https://www.cnblogs.com/cao-lei/p/8328160.html
Copyright © 2011-2022 走看看