本文已参加【新人创作礼】活动,一起开启掘金创作之路。
概念
职责链模式(Chain of Responsibility Pattern):避免将请求发送者与接收者耦合在一起,让多个对象都有机会接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。
角色
- Handler(抽象处理者):它定义了一个处理请求的接口,一般设计为抽象类。由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。因为每个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个抽象处理者类型的对象(结构图中的successor),作为其对下家的引用。通过该引用,处理者可以连成一条链。
- ConcreteHandler(具体处理者):它是抽象处理者的子类,可以处理用户请求。在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者。在具体处理者中可以访问链中下一个对象,以便请求的转发。
样例代码
abstract calss handler {
// 维持下家的引用
protected handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(Object request);
}
class ConcreteHandler extends Handler {
public void handleRequest (Object request) {
if (请求满足条件) {
// 处理请求
} else {
this.successor.handleRequest(request); // 向下家转发请求
}
}
}
具体案例
采购审批子系统。该企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批
设计方案中包含:抽象类Approver充当抽象处理者,Director(主任)、VicePresident(副董事长)、President(董事长)和Congress(董事会)充当具体处理者,PurchaseRequest请求类(采购单)。
完整代码如下:
纯与不纯的职责链模式
职责链模式可分为纯的职责链模式和不纯的职责链模式两种。
纯的职责链模式
一个纯的职责链模式要求一个具体处理者对象只能在两个行为中选择一个:要么承担全部责任,要么将责任推给下家。不允许出现某一个具体处理者对象在承担了一部分或全部责任后又将责任向下传递的情况。而且在纯的职责链模式中,要求一个请求必须被某一个处理者对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况。
不纯的职责链模式
在一个不纯的职责链模式中,允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某请求后其后继处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收。例如窗口组件(例如按钮、文本框等)点击。
总结
优点
- 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求。对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构。由客户端负责链的创建,降低了系统的耦合度。
- 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。
- 在给对象分派职责时,职责链可以提供更多的灵活性,可以通过在运行时对链进行动态的增加或修改来增加或改变处理一个请求的职责。
- 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合开闭原则的。
缺点
- 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理。一个请求也可能因职责链没有被正确配置而得不到处理。
- 对于比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。
- 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。
参考资料
[1] 刘伟. 设计模式的艺术[M]. 清华大学出版社, 2020.