前言
- 掌握责任链模式的应用常见
- 深刻理解责任链模式和建造者模式的结合应用
一、定义
责任链模式(Chain of Responsibility):为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过
前一对象记住其下一对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
二、应用场景
- 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定
- 可动态指定一组对象处理请求,或添加新的处理者
- 需要在不明确指定请求处理者的情况下,想多个处理者中的一个提交请求
三、基本结构
- 抽象处理者角色(Handler):定义一个处理请求的接口,包含抽象处理方法和一个后继处理节点对象的引用
- 具体处理者角色(Concrete Handler):实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者
- 客户端角色(Client):创建处理链,并向链头的具体处理者对象提交请求,他不关心处理细节和请求的传递过程
四、基本使用
1. 抽象处理者角色
public abstract class Handler {
protected Handler handler;
private void next(Handler handler) {
this.handler = handler;
}
public abstract void handleRequest(String request);
public static class Builder{
private Handler head;
private Handler tail;
public Builder addHandler(Handler handler) {
if (this.head == null) {
this.head = this.tail = handler;
return this;
}
this.tail.next(handler);
this.tail = handler;
return this;
}
public Handler build() {
return this.head;
}
}
}
2. 具体处理者角色
public class ConcreteHandler1 extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("1")) {
System.out.println("具体处理者1处理请求");
} else {
handler.handleRequest(request);
}
}
}
public class ConcreteHandler2 extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("2")) {
System.out.println("具体处理者2处理请求");
} else if (handler != null) {
handler.handleRequest(request);
} else {
System.out.println("没有对应的处理者");
}
}
}
3. 客户端角色
public class Client {
public static void main(String[] args) {
Handler.Builder builder = new Handler.Builder();
builder.addHandler(new ConcreteHandler1())
.addHandler(new ConcreteHandler2());
builder.build().handleRequest("2");
}
}
总结
1. 优点
- 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方明确信息
- 增加了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则
- 增加了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调整它们的次序,也可以动态地新增或删除责任
- 责任链简化了对象之间的连接。每个对象只需保持一个指向后继者的引用,不需要保持其他所有处理者的引用,避免了使用众多的if或if…else语句
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则
2. 缺点
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理
- 对比较长的责任链,请求的处理可能涉及多个处理对象,系统性能对象受到一定影响
- 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于责任链的错误设置而导致系统出错,如可能造成循环调用