设计模式专栏-责任链模式

104 阅读4分钟

责任链模式

1.什么是责任链模式

  • 责任链模式是一种由命令对象的源和一系列处理对象组成的设计模式。每个处理对象都包含定义其可以处理的命令对象类型的逻辑。其余的将传递到链中的下一个处理对象。

2.应用

2.1 应用场景

责任链模式的使用也是比较广泛的,比如我们OA系统的审批流,或者某一个特殊的业务需要经过几个比较复杂的流程处理等,比如一个添加业务,假设我们先要进行数据校验,然后进行入库操作,最后要通知其他系统做特殊处理,就可以做成一个责任链模式,代码整体耦合性降低,易于维护

2.2 角色

  • Handler(抽象处理者)

    定义请求处理方法,以及维护下一个处理者的引用

  • ConcreteHandler(具体处理者)

    处理请求的具体角色

3.类图

责任链模式的类图比较简单,所有处理节点都继承同一个父类,这个父类可以是抽象类或者具体实现类,类中维护下一个处理节点的引用以及节点的处理请求方法(这个方法可以是抽象方法,也可以是具体实现,当然还可以利用钩子方法实现对子类方法的调用),调用者不关注具体节点的实现,只调用节点的处理方法即可。

image-20231113174615002.png

4. 举例说明

假设现在有一个请假流程,小于三天组长审批即可,大于3天同时需要CTO审批,大于10天同时需要CEO审批。组长和CTO以及CEO都有权利审批通过或者驳回,如果审批通过,根据请假天数判断是否需要流转到下一节点,如果驳回请求,则直接返回。

image-20231113174802271.png

五. 优缺点

优点:
  • 降低代码的耦合度,将请求与处理解耦
  • 节点对象只需关注自己要处理的业务或者特定的请求即可,对于不想处理的可以直接传递给下一个节点
  • 链路结构灵活,可以通过改变链路结构动态的新增或者删减责任
  • 可以实时新增链路节点,符合开闭原则
缺点:
  • 责任链太长或者处理时间过长,会影响整体性能
  • 整体调用有点类似递归,排查问题较为费力
  • 代码拆分的小类会比较多

6.示例代码

hander

public class Handler {
​
    private Handler next;
​
    public Handler(Handler next) {
        this.next = next;
    }
​
    public void HandlerProcess(Request request){
        if(next!=null){
            next.HandlerProcess(request);
        }
    }
}
​

Request

public class Request {
    private String employeeName; // 员工姓名
​
    private int days; // 请假天数
​
    private boolean handleResult; // 请假是否通过
​
    public Request(String employeeName, int days) {
        this.employeeName = employeeName;
        this.days = days;
    }
​
    public String getEmployeeName() {
        return employeeName;
    }
​
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
​
    public int getDays() {
        return days;
    }
​
    public void setDays(int days) {
        this.days = days;
    }
​
    public void setPass() {
        this.handleResult = true;
    }
​
    public void setReject() {
        this.handleResult = false;
    }
​
    public boolean getHandleResult() {
        return this.handleResult;
    }
​

具体的子类实现。LeaderOne LeaderTwo LeaderThree

/**
 * 审批者1
 */
public class LeaderOne extends Handler{
​
    public LeaderOne(Handler next) {
        super(next);
    }
​
    @Override
    public void HandlerProcess(Request request){
​
        if(request.getEmployeeName().equals("王炼")){
            System.out.println("LeaderOne 驳回"+request.getEmployeeName()+"的请假");
            request.setReject();
            return;
        }
         System.out.println("LeaderOne 通过"+request.getEmployeeName()+"的请假");
        if(request.getDays()>3) {
            super.HandlerProcess(request);
        }else{
            request.setPass();
        }
    }
}
/**
 * 审批者2
 */
public class LeaderTwo extends Handler{
​
    public LeaderTwo(Handler next) {
        super(next);
    }
​
    @Override
    public void HandlerProcess(Request request){
​
        if(request.getEmployeeName().equals("王佳颖")){
            System.out.println("LeaderTwo 驳回"+request.getEmployeeName()+"的请假");
            request.setReject();
            return;
        }
         System.out.println("LeaderTwo 通过"+request.getEmployeeName()+"的请假");
        if(request.getDays()>6) {
            super.HandlerProcess(request);
        }else{
            request.setPass();
        }
    }
}
​
/**
 * 审批者3
 */
public class LeaderThree extends Handler{
​
    public LeaderThree(Handler next) {
        super(next);
    }
​
    @Override
    public void HandlerProcess(Request request){
        if(request.getEmployeeName().equals("大笨蛋")){
            request.setReject();
            System.out.println("LeaderThree 驳回"+request.getEmployeeName()+"的请假");
            return;}else{
        System.out.println("LeaderThree 通过"+request.getEmployeeName()+"的请假");
        request.setPass();}
        if(request.getDays()>10) {
            super.HandlerProcess(request);
        }
    }
}
​

测试代码

public class Test {
    public static void main(String[] args) {
        LeaderOne leaderOne = new LeaderOne(new LeaderTwo(new LeaderThree(null)));
        Request request = new Request("王炼",4);
        leaderOne.HandlerProcess(request);
        System.out.println("请假结果="+request.getHandleResult());
​
        System.out.println("---------------------------------------------");
        Request request1 = new Request("王炼1",4);
        leaderOne.HandlerProcess(request1);
        System.out.println("请假结果="+request1.getHandleResult());
​
        System.out.println("---------------------------------------------");
        Request request2 = new Request("王佳颖",4);
        leaderOne.HandlerProcess(request2);
        System.out.println("请假结果="+request2.getHandleResult());
​
        System.out.println("---------------------------------------------");
        Request request3 = new Request("王胖胖",4);
        leaderOne.HandlerProcess(request3);
        System.out.println("请假结果="+request3.getHandleResult());
​
​
        System.out.println("---------------------------------------------");
        Request request4 = new Request("王壮壮",11);
        leaderOne.HandlerProcess(request4);
        System.out.println("请假结果="+request4.getHandleResult());
​
        System.out.println("---------------------------------------------");
        Request request5 = new Request("大笨蛋",11);
        leaderOne.HandlerProcess(request5);
        System.out.println("请假结果="+request5.getHandleResult());
    }
}
​
​
输出结果:
 LeaderOne 驳回王炼的请假
请假结果=false
---------------------------------------------
LeaderOne 通过王炼1的请假
LeaderTwo 通过王炼1的请假
请假结果=true
---------------------------------------------
LeaderOne 通过王佳颖的请假
LeaderTwo 驳回王佳颖的请假
请假结果=false
---------------------------------------------
LeaderOne 通过王胖胖的请假
LeaderTwo 通过王胖胖的请假
请假结果=true
---------------------------------------------
LeaderOne 通过王壮壮的请假
LeaderTwo 通过王壮壮的请假
LeaderThree 通过王壮壮的请假
请假结果=true
---------------------------------------------
LeaderOne 通过大笨蛋的请假
LeaderTwo 通过大笨蛋的请假
LeaderThree 驳回大笨蛋的请假
请假结果=false