文章目录
- 1、要点
- 2、Demo
- 3、进阶掌握
参考文章:
基本原理:责任链模式 | 菜鸟教程 (runoob.com)
简单例子:五分钟学设计模式.12.责任链模式_哔哩哔哩_bilibili
阿里巴巴的应用:责任链模式在复杂数据处理场景中的实战
责任链模式(Chain of Responsibility Pattern)指的是为请求创建了一个处理对象的链。这种模式将请求者和处理者进行解耦,请求者不需要知道谁去处理,处理者也不需要知道请求的全貌。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个处理者都包含对另一个处理者的引用。如果一个链上的处理者不能处理该请求,那么它会把相同的请求传给下一个处理者,依此类推。
1、要点
意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
何时使用:在处理消息的时候以过滤很多道。
如何解决:链上的处理类都继承同一抽象类,同时能够通过构造函数或者set设置下一个处理节点。
应用实例: 1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
缺点: 1、系统性能将受到一定影响,每次都需要从链头走到链尾。 2、在进行代码调试时不太方便,采取类似递归的方式,查错较难。3、可能会造成循环调用
使用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。
**注意事项:**在 JAVA WEB 中遇到很多应用。
2、Demo
现在要实现一个请假审批请求的流程,依次需要经过 班长 - 辅导员 - 校长的审批。
实现要点:需要定义一个总抽象类Handler,规定责任链上的处理节点的结构,该类中还需要有下一个节点设置方法(这里采用set设置),处理方法process()根据规则判断在当前节点处理,还是传递给下一个节点。
-
定义链节点抽象类
/** * @Author jiangxuzhao * @Description 定义链节点抽象类 * @Date 2023/5/22 */ public abstract class Handler { protected Handler nextHandler; public void setNextHandler(Handler nextHandler){ this.nextHandler=nextHandler; } // 根据紧急程度urgentDegree传递请求request public abstract void process(Integer urgentDegree, String request); }
-
定义具体的链节点
/** * @Author jiangxuzhao * @Description 班长责任节点 * @Date 2023/5/22 */ public class ClassMonitor extends Handler{ @Override public void process(Integer urgentDegree, String request) { if(urgentDegree>=0&&urgentDegree<10){ System.out.println("班长审批了: "); }else{ System.out.println("班长没法审批,传下去..."); nextHandler.process(urgentDegree,request); } } }
/** * @Author jiangxuzhao * @Description 辅导员责任节点 * @Date 2023/5/22 */ public class Counsellor extends Handler{ @Override public void process(Integer urgentDegree, String request) { if(urgentDegree>=10&&urgentDegree<20){ System.out.println("辅导员审批了: "+request); }else{ System.out.println("辅导员没法审批,传下去..."); nextHandler.process(urgentDegree, request); } } }
/** * @Author jiangxuzhao * @Description 校长责任节点 * @Date 2023/5/22 */ public class SchoolMaster extends Handler{ @Override public void process(Integer urgentDegree, String request) { System.out.println("终极一站,校长审批了: "+request); } }
-
测试,需要自己先设置好责任链,一次设置,多次调用
import org.junit.Test; /** * @Author jiangxuzhao * @Description * @Date 2023/5/22 */ public class TestResponsibilityChain { @Test public void testChain(){ // 创建责任链节点 Handler level1 = new ClassMonitor(); Handler level2 = new Counsellor(); Handler level3 = new SchoolMaster(); // 设置责任链 level1.setNextHandler(level2); level2.setNextHandler(level3); // 测试,从第一个节点传入请求 level1.process(15,"出去上网"); System.out.println(); level1.process(100,"出去看病"); } }
输出:
3、进阶掌握
在理解了原理之后,更高阶的实际应用可以参考阿里巴巴的技术文章责任链模式在复杂数据处理场景中的实战