责任链模式(Chain of Responsibility),在企业中,主要用来解决一些复杂的逻辑,允许你将请求沿着处理者链进行发送。收到请求后,每个处理
者均可对请求进行处理,或将其传递给链上的下个处理者。责任链模式也经常用于较复杂的过滤器设计当中。责任链模式也叫作「职责链模式」,属于十一个行为型模式之一,行为模式负责对象间的高效沟通和职责委派,其余十个分别为:
- 观察者模式-Observer Pattern
- 命令模式-Command Pattern
- 解释器模式-Interpreter Pattern
- 迭代器模式-Iterator Pattern
- 中介者模式-Mediator Pattern
- 备忘录模式-Memento Pattern
- 状态模式-State Pattern
- 策略模式-Strategy Pattern
- 模板方法模式-Template Method Pattern
- 访问者模式-Visitor Pattern
其中状态模式、策略模式、模板方法模式、观察者模式老四之前已经写过相关文章,可参考文末相关阅读。
责任链模式定义
职责链模式是指为了避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。对于客户端,并不知道最终处理请求是链上的哪个对象。
职责链模式结构及其相关角色
- Handler(抽象处理者):它定义了一个处理请求的接口(抽象类),定义抽象请求处理方法和一个抽象处理者类型的对象,抽象处理者类型的对象作为其对下家的引用,通过该引用,处理者可以连成一条链。抽象请求处理方法供子类(具体处理者)进行实现具体的业务逻辑。
- ConcreteHandler(具体处理者):它是抽象处理者的子类,可以处理用户请求,在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者;在具体处理者中可以访问链中下一个对象,以便请求的转发。
- BaseHandler(基础处理者,可选):设置默认的处理行为,可以放置所有处理者公用的代码。
如上所述,职责链的核心比较简单,主要结构示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package learn.design.patterns.chainofresponsibility; /** * 抽象处理类 * * @author : 高老四 * @ClassName : Handler * @since : 2022/3/13 21:38 */ public abstract class Handler { public Handler handler; public abstract void handleReuqest(String request); public void setHandler(Handler handler) { this.handler = handler; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package learn.design.patterns.chainofresponsibility; /** * 具体处理者 * * @author : 高老四 * @ClassName : ConcreteHandler * @since : 2022/3/13 21:41 */ public class ConcreteHandlerOne extends Handler { @Override public void handleReuqest(String request) { if (true) { System.out.println("https://www.oom.cool/"); } else { this.handler.handleReuqest(request); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package learn.design.patterns.chainofresponsibility; /** * 具体处理者 * * @author : 高老四 * @ClassName : ConcreteHandler * @since : 2022/3/13 21:41 */ public class ConcreteHandlerTwo extends Handler { @Override public void handleReuqest(String request) { if (true) { System.out.println("http://www.downhub.net/"); } else { this.handler.handleReuqest(request); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package learn.design.patterns.chainofresponsibility; /** * 客户端 * * @author : 高老四 * @ClassName : Client * @since : 2022/3/13 21:43 */ public class Client { public static void main(String[] args) { Handler handler = new ConcreteHandlerOne(); handler.setHandler(new ConcreteHandlerTwo()); handler.handleReuqest("oom.cool"); } } |
如上代码所示,就是责任链的核心结构了,每个处理者除了负责处理请求以外,还负责沿着链进行请求传递,从而让所有处理者都有机会进行请求处理。实现客户端与真正的业务服务端解耦,也符合「开闭原则」,对于新增的链节点或者链节点需要变动的情况,都统一交由客户端进行定义和处理,满足单一职责。
责任链的类型
纯的责任链
纯的责任链如上代码所示,要求两点:
- 一个具体处理者对象只能在两个行为中选择一个,要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或全部责任后又将责任向下传递的情况。
- 一个请求必须被某一个处理者对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况。
不纯的职责链
但是一般我们再开发业务的过程当中,很少会用到纯的责任链,比如 Servlet 中的过滤器,他们都是每个处理者承担一部分职责之后,交由下一个具体处理着继续进行业务的处理。
所以在在一个不纯的职责链模式中,允许某个请求被一个具体处理者部分处理后再向下传递,或者说一个具体处理者处理完某请求后其后继处理者可以继续处理该请求,并且一个请求可以最终不被任何处理者对象所接收。
责任链的优势
- 客户端和服务端解耦,客户端负责链的创建,服务端链对象不需要知道链的结构,降低系统耦合度
- 具体处理者仅需维护下一个具体处理者的引用,简化对象连接
- 增强灵活性,客户端可以根据业务的动态变化随时进行链结构的修改
- 符合「开闭原则」,无需修改原有代码即可新增或者减少链结构。
职责链的劣势
- 如果是不纯的职责链,那么客户端的一个请求可能没有被处理
- 链结构设计不当,可能会带来死循环
- 如果链比较长,会降低系统性能。
责任链的使用场景
-
当程序需要使用不同方式处理不同种类请求,而且请求类型和顺序预先未知。
-
必须按顺序执行多个处理者
-
所需处理者及其顺序必须在运行时进行改变
责任链其实也适合比较简单的「流程引擎」,当你的业务具有一定的规模,并且有着比较明确的流程步骤的时候,那么处理一个请求,可能会分为一系列的步骤,比如参数校验、数据查询、数据处理、响应结果,那么对于类似这样的流程框架,可以使用职责链进行整体的流程控制,一步一步进行你的业务处理。
此外,责任链在「过滤器」中使用比较广泛,过滤器由于经常在开发中得到使用,现在越来越多的资料将其作为一种新的设计模式来进行介绍,但是其本质还是责任链模式。
相关文章阅读
更博不易,如果觉得文章对你有帮助并且有能力的老铁烦请捐赠盒烟钱,点我去赞助。或者扫描文章下面的微信/支付宝二维码打赏任意金额(点击「给你买杜蕾斯」),也可以加入本站封闭式交流论坛「DownHub」开启新世界的大门,老四这里抱拳谢谢诸位了。捐赠时请备注姓名或者昵称,因为您的署名会出现在赞赏列表页面,您的捐赠钱财也会被用于小站的服务器运维上面,再次抱拳感谢。