责任链模式(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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。