描述
定义
由对象自身及对下家的引用而连接形成一条对象链,请求在这个链上传递,直到链上的某一个对象决定处理此请求,这叫做责任链模式。
类型
对象行为型模式
动机
解耦发送者和接受者。请求沿对象链传递直到其中一个对象处理它。从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者。提交请求的对象并不明确地知道哪一个对象将会处理它。
UML类图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KGcfH93K-1599477672133)(https://i.imgur.com/RROX2Im.jpg)]
时序图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4HMpQVjC-1599477672136)(https://i.imgur.com/9TwLG8v.jpg)]
实现
主要角色
- Handler
- 定义一个处理请求的接口;
- (可选)实现后继链;
- ConcreteHandler
- 处理它所负责的请求;
- 可访问它的后继者;
- 如果可处理该请求,则处理之;否则将该请求转发给它的后继者;
- Client
- 向链上的具体处理者(ConcreteHandler)对象提交请求;
示例
-
Handler:请求处理的接口类
public abstract class Handler { // 持有后继的责任对象 protected Handler successor; // 处理请求的方法,可根据具体需要来选择是否传递参数 public abstract void handleRequest(); public Handler getSuccessor() { return successor; } public void setSuccessor(Handler successor) { this.successor = successor; } }
-
ConcreteHandler:具体请求处理子类
public class ConcreteHandlerA extends Handler { @Override public void handleRequest() { // 这是一种简单实现,具体子类可定义不同的请求分发方法 if (getSuccessor() != null) { getSuccessor().handleRequest(); } else { System.out.println("处理请求"); } } } public class ConcreteHandlerB extends Handler { @Override public void handleRequest() { // 这是一种简单实现,具体子类可定义不同的请求分发方法 if (canHandle()) { System.out.println("处理请求"); } else if (getSuccessor() != null) { getSuccessor().handleRequest(); } else { System.out.println("请求无法处理!"); } } // 判断当前类是否可处理该请求,这只是一个空实现的示例 private boolean canHandle() {return true;} }
-
Client:发起请求的客户类
public class Client { public static void main(String[] args) { //组装责任链 Handler handler1 = new ConcreteHandlerA(); Handler handler2 = new ConcreteHandlerB(); handler1.setSuccessor(handler2); //提交请求 handler1.handleRequest(); } }
适用场景
- 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
- 可处理一个请求的对象集合应被动态指定;
优点
- 降低耦合度。该模式使得客户端无需知道是哪一个对象处理该请求,将请求的发送者和接收者解耦。
- 简化对象的相互连接。链中的对象不需知道链的结构。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。
- 增强给对象指派职责的灵活性。可通过在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
- 方便扩展请求处理类;
缺点
- 不保证被接收:既然一个请求没有明确的接收者,那么就不能保证它一定会被处理——该请求可能一直到链的末端都得不到处理。
相关模式
职责链常与Composite一起使用。这种情况下,一个构件的父构件可作为它的后继。