头图
责任链模式(Chain of Responsibility Pattern)属于行为型模式

概述

责任链,即责任的链条,在生活中是很常见的。

比如在工作中提交审批,会经历责任人的层层审批,最后才会通过,这一审批流程就是责任链。

再比如,JavaWeb 中学习的 Filter 过滤器,正是采用的责任链模式,通过将请求一级一级不断向下传递,来对所需要的请求进行过滤和处理。

运用责任链模式,可以让整个流程变得更加清晰,且每个环节的调用顺序可以灵活的调整,利于维护和扩展。

代码实现

这里以面试过程为例介绍责任链模式:

1、定义面试处理程序

/**
 * 面试处理程序
 */
public abstract class Handler {

    /**
     * 下一轮面试
     */
    protected Handler successor;

    /**
     * 开始下一轮面试
     * @param successor 下一轮面试
     * @return 面试处理程序
     */
    public Handler connect(Handler successor) {
        
        this.successor = successor;
        // 这里返回后继节点,方便后面链式调用
        return successor;
    }

    /**
     * 开始面试
     */
    public void handle() {

        // 面试过程。由不同的子类实现具体处理过程
        this.doHandle();
        //责任链上如果还有后继节点,就继续向下传递
        Optional.ofNullable(this.successor).ifPresent(Handler::handle);
    }

    /**
     * 面试过程<br>
     * 采用模板模式,变化的逻辑定义为抽象的,交由子类继承实现
     */
    public abstract void doHandle();

}

2、定义第一轮面试

/**
 * 第一轮面试
 */
public class FirstHandler extends Handler {

    @Override
    public void doHandle() {
        System.out.println("第一轮面试");
    }
}

3、定义第二轮面试

/**
 * 第二轮面试
 */
public class SecondHandler extends Handler {
    
    @Override
    public void doHandle() {
        System.out.println("第二轮面试");
    }
}

4、定义第三轮面试

/**
 * 第三轮面试
 *
 * @author CodeSail
 * @date 2022-08-14 15:39:52
 */
public class ThirdHandler extends Handler {
    
    @Override
    public void doHandle() {
        System.out.println("第三轮面试");
    }
}

5、调用

// 首先定义第一轮面试
Handler handler = new FirstHandler();
// 连接后续两轮面试
handler.connect(new SecondHandler()).connect(new ThirdHandler());
// 开始面试
handler.handle();

输出结果为:

第一轮面试
第二轮面试
第三轮面试

这样就实现按照预定的顺序的三轮面试。如果需要将第三轮面试调整到第二轮之前,只需要将连接顺序改变即可:

handler.connect(new ThirdHandler()).connect(new SecondHandler());

这样的输出就变成了:

第一轮面试
第三轮面试
第二轮面试

这就是责任链模式的好处,可以非常方便的对流程进行调整和控制。

优缺点

优点

1、降低耦合度。将请求的发送者和接收者解耦。

2、简化了对象。使得对象不需要知道链的结构,只负责自己的逻辑定义即可。

3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的顺序,可以动态地新增或者删除责任。

4、增加新的请求处理类很方便。

缺点

1、不能保证请求一定被接收。

2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。

3、可能不容易观察运行时的特征,有碍于除错。

使用场景

1、多个对象处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。

2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。

3、可动态指定一组对象处理请求。

注意事项

在需要使用链式调用的场景都可以考虑使用责任链模式(Java Web中尤其多)。


参考

https://www.bilibili.com/video/BV1u3411P7Na?p=23\&vd\_source=299f4bc123b19e7d6f66fefd8f124a03


天航星
1 声望0 粉丝

天河有尽后为涯,星海无边前作岸。