Appearance
责任链模式(Chain of Responsibility Pattern)笔记
定义
责任链模式是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
英文原文定义:
The Chain of Responsibility Pattern avoids coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
核心概念
责任链模式通过建立处理对象的链式结构,使请求可以沿着链传递,直到被某个处理者处理。这种模式实现了请求发送者和接收者的解耦。
主要角色
- Handler(抽象处理者):定义处理请求的接口,通常包含设置后继者的方法
- ConcreteHandler(具体处理者):实现处理请求的具体逻辑,可以访问后继者
- Client(客户端):创建处理链,并向链头的处理者提交请求
优缺点
优点
- 降低耦合度:请求发送者不需要知道哪个对象会处理请求
- 动态灵活:可以在运行时动态改变链中的处理者或它们的顺序
- 单一职责原则:每个处理者只需关注自己处理的请求
- 开闭原则:可以新增处理者而不修改现有代码
缺点
- 请求可能未被处理:如果链配置不当,请求可能到达链尾都未被处理
- 性能影响:较长的责任链可能影响性能(可通过非纯责任链优化)
- 调试困难:请求的传递过程可能使调试变得复杂
解决的问题
责任链模式主要解决以下经典问题:
- 多条件流程处理:当需要多个条件判断分支处理请求时
- 动态指定处理者:当处理请求的对象需要动态指定时
- 解耦请求发送者和接收者:当不希望明确指定请求接收者时
- 审批流程:多级审批、权限检查等场景
实现注意事项
链的构建方式:
- 客户端显式构建(更灵活)
- 处理者自组织构建(更内聚)
请求传递控制:
- 纯责任链:必须被某个处理者处理
- 非纯责任链:允许不被处理
后继者引用:
- 可以定义在抽象处理者中(所有子类共享)
- 也可以由具体处理者自行维护
请求对象设计:
- 包含处理所需的所有信息
- 可以考虑包含处理状态
性能优化:
- 对于长链,可以考虑短路处理(提前终止)
- 缓存常用处理路径
实现变体
纯责任链:
- 请求必须被处理
- 每个处理者要么处理请求,要么传递给下一个
非纯责任链:
- 请求可能不被处理
- 更常见于实际应用
功能链:
- 每个处理者对请求进行部分处理
- 类似于管道过滤器模式
树形结构链:
- 处理者形成树形结构
- 请求可以沿多个路径传递
与其他模式的关系
相似模式区分
装饰器模式:
- 责任链:处理者决定是否处理请求
- 装饰器:所有装饰者都会参与处理
命令模式:
- 责任链:多个处理者选择执行
- 命令:将请求封装为对象
组合模式:
- 责任链:处理者形成链式结构
- 组合:处理者形成树形结构
常见搭配组合
- 责任链 + 组合:构建树形处理结构
- 责任链 + 策略:不同处理者使用不同策略
- 责任链 + 模板方法:处理流程中应用模板方法
- 责任链 + 享元:共享处理者实例
典型应用场景
- 异常处理(try-catch-finally块)
- 事件冒泡(GUI事件处理)
- 审批工作流(采购审批、请假审批)
- Web请求过滤器(Servlet Filter)
- 日志记录器(不同级别的日志处理)
- 游戏中的输入处理
代码示例(请假审批实现)
java
// 抽象处理者
abstract class Approver {
protected Approver successor;
public void setSuccessor(Approver successor) {
this.successor = successor;
}
public abstract void processRequest(LeaveRequest request);
}
// 具体处理者:主管
class Supervisor extends Approver {
@Override
public void processRequest(LeaveRequest request) {
if (request.getDays() <= 3) {
System.out.println("Supervisor approved leave for " + request.getDays() + " days");
} else if (successor != null) {
successor.processRequest(request);
}
}
}
// 具体处理者:经理
class Manager extends Approver {
@Override
public void processRequest(LeaveRequest request) {
if (request.getDays() <= 10) {
System.out.println("Manager approved leave for " + request.getDays() + " days");
} else if (successor != null) {
successor.processRequest(request);
}
}
}
// 具体处理者:总监
class Director extends Approver {
@Override
public void processRequest(LeaveRequest request) {
System.out.println("Director approved leave for " + request.getDays() + " days");
}
}
// 请求类
class LeaveRequest {
private int days;
private String reason;
// 构造方法和getter省略
}
// 客户端代码
Approver supervisor = new Supervisor();
Approver manager = new Manager();
Approver director = new Director();
supervisor.setSuccessor(manager);
manager.setSuccessor(director);
LeaveRequest request1 = new LeaveRequest(2, "Family event");
supervisor.processRequest(request1);
LeaveRequest request2 = new LeaveRequest(5, "Medical leave");
supervisor.processRequest(request2);