1.什么是责任链设计模式

责任链设计模式主要构成有抽象处理者、具体处理者、客户类,在处理请求的时候,将请求通过客户类发送至处理链路上,这样所有处理对象都有机会处理请求,使发送者与接受者解耦

在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,所以责任链将请求的发送者和请求的处理者解耦了。
在这里插入图片描述

2.责任链模式的优点/缺点和使用场景

使用责任链模式的优点:

  • 发送者与接收方的处理对象类之间解耦
  • 封装每个处理对象,处理类的最小封装原则
  • 可以任意添加处理对象,调整处理对象之间的顺序,提高了维护性和可拓展性可以根据需求新增处理类,满足开闭原则
  • 增强了对象职责指派的灵活性,当流程发生变化的时候可以动态的改变链内的调动次序可动态的新增或者删除
  • 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
  • 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

使用责任链模式的缺点:

  • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

使用场景:

当请求来到时,不知道由哪一个具体的对象(方法)或者每个对象都需要处理请求的时候,可以使用责任链模式。比如在常见的OA办公系统,当一个员工发起请假的申请,需要经过(开发组长-部门经理-总经理等)使用不同的封装类组成一个处理链路,使用这个处理链路去处理该员工发起的请求

在这里插入图片描述

3.责任链模式与策略模式的区别

策略模式和责任链模式很像,都是有多个对象去处理同一个请求

不同之处在于对于同一个请求,策略模式是可以选择哪个具体的策略类来进行处理而责任链模式不能根据请求去判断使用哪个类来处理,需要链路上的处理类 全部来处理一遍才能得出结果

4. JAVA 代码演示

4.1.编写责任链处理Handler

package com.zhangsan.shard.handler;

import lombok.Data;

/**
 * @ClassName DutyHandler
 * @Description TODO
 * @Author ZhangSan_Plus
 * @Date 2021/9/2 16:23
 * @Version 1.0
 **/
@Data
public abstract class DutyHandler {
    protected DutyHandler successor;

    /**
     * 请假审批接口
     *
     * @param message
     * @param days
     * @return boolean
     * @throws
     * @author ZhangSan_Plus
     * @Date 2021/9/2 16:56
     **/
    public abstract boolean dutyHandler(String message, Integer days);

}

4.2 编写开发经理对应的实现

package com.zhangsan.shard.handler;

/**
 * @ClassName ProcessorOne
 * @Description TODO
 * @Author ZhangSan_Plus
 * @Date 2021/9/2 16:26
 * @Version 1.0
 **/
public class ProcessorOne extends DutyHandler {
    /**
     * 假设开发经理只能处理请假小于1天以内的
     */
    @Override
    public boolean dutyHandler(String message, Integer days) {
        System.out.println("处理请求:" + message);
        System.out.println("请假天数:" + days);
        if (days <= 1) {
            System.out.println("开发经理审批通过");
            return true;
        } else {
            System.out.println("请假天数大于一天,开发经理无法处理,交给项目经理处理");
            setSuccessor(new ProcessorTwo());
            System.out.println("=====================================");
            return successor.dutyHandler(message, days);
        }

    }

    @Override
    public void setSuccessor(DutyHandler dutyHandler) {
        this.successor = dutyHandler;
    }

    @Override
    public DutyHandler getSuccessor() {
        return successor;
    }
}

4.3 编写项目经理的对应实现

package com.zhangsan.shard.handler;

/**
 * @ClassName ProcessorTwo
 * @Description TODO
 * @Author ZhangSan_Plus
 * @Date 2021/9/2 16:33
 * @Version 1.0
 **/
public class ProcessorTwo extends DutyHandler {
    /**
     * 假设项目经理只能处理10天或者10天以内的审批
     */
    @Override
    public boolean dutyHandler(String message, Integer days) {
        System.out.println("处理请求:" + message);
        System.out.println("请假天数:" + days);
        if (days <= 10) {
            System.out.println("项目经理审批通过");
            return true;
        } else {
            System.out.println("请假天数大于十天,项目经理无法处理,交给总记录处理");
            setSuccessor(new ProcessorThree());
            System.out.println("=====================================");
            return successor.dutyHandler(message, days);
        }

    }

    @Override
    public void setSuccessor(DutyHandler dutyHandler) {
        this.successor = dutyHandler;
    }

    @Override
    public DutyHandler getSuccessor() {
        return successor;
    }
}

4.4 编写总经理对应的实现

package com.zhangsan.shard.handler;

/**
 * @ClassName ProcessorThree
 * @Description TODO
 * @Author ZhangSan_Plus
 * @Date 2021/9/2 16:50
 * @Version 1.0
 **/
public class ProcessorThree extends DutyHandler {
    /**
     * 总经理可以处理全部天数的审批
     */
    @Override
    public boolean dutyHandler(String message, Integer days) {
        System.out.println("处理请求:" + message);
        System.out.println("请假天数:" + days);
        System.out.println("总经理审批通过");
        return true;
    }

    @Override
    public void setSuccessor(DutyHandler dutyHandler) {
        this.successor = dutyHandler;
    }

    @Override
    public DutyHandler getSuccessor() {
        return successor;
    }
}

4.5 编写员工请假审批模拟

package com.zhangsan.shard.handler;

/**
 * @ClassName Staff
 * @Description TODO
 * @Author ZhangSan_Plus
 * @Date 2021/9/2 16:52
 * @Version 1.0
 **/
public class Staff {
    public static void main(String[] args) {
        ProcessorOne processorOne = new ProcessorOne();
        processorOne.dutyHandler("张三提交请假审批", 15);
    }
}

4.6 具体执行结果

在这里插入图片描述

5. 责任链模式的扩展

5.1 纯的职责链模式

一个纯的职责链模式要求一个具体处理者对象只能在两个行为中选择一个:要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或全部责任后又将责任向下传递的情况。而且在纯的职责链模式中,要求一个请求必须被某一个处理者对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况。在前面的采购单审批实例中应用的是纯的职责链模式。

5.2 不纯的职责链模式

允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且一个请求可以最终不被任何接收端对象所接收。

Q.E.D.