责任链模式是什么
让多个处理者依次尝试处理请求,每个处理者自己决定是处理、是继续传递、还是终止:校验链、审批流、过滤器、中间件都是它的形态。它把「谁处理」与「处理顺序」从调用方解耦,代价是请求的最终归宿不再写在调用处——因此链的装配顺序与兜底行为必须显式。
基本信息
| 意图 | 请求沿链传递,处理者彼此解耦 |
|---|---|
| 场景 | 审批流、校验链、过滤链、中间件、事件处理 |
| 要点 | 终态处理与顺序显式化 |
| 变体 | 链上节点也可决定不处理,或处理后继续传递 |
典型使用场景
- 表单校验:非空、格式、业务规则分节点,便于按需组合
- 审批流:按金额或类型选择审批层级,节点可动态装配
- HTTP 中间件:日志、鉴权、限流、压缩依次处理同一请求
- 事件处理:多个订阅者按顺序响应,任一节点可终止后续
- 兼容升级:新版处理器在前,旧版兜底在后,逐日下线旧逻辑
Java 示例
Java 示例
abstract class Handler {
private Handler next;
Handler link(Handler next) { this.next = next; return next; }
final void handle(Request r) {
if (canHandle(r)) {
process(r);
return; // 处理完即终止,语义要显式
}
if (next != null) {
next.handle(r);
} else {
throw new IllegalStateException("no handler for " + r.type());
}
}
abstract boolean canHandle(Request r);
abstract void process(Request r);
}装配方式对照
| 装配方式 | 可读性 | 适用 |
|---|---|---|
| 构造函数内链式装配 | 高,顺序一眼可见 | 节点固定、顺序稳定的链 |
| 配置驱动装配 | 中,需读配置才知顺序 | 不同租户或环境顺序不同 |
| 注解或自动扫描 | 低,顺序靠约定 | 框架中间件,需文档明确 |
| 运行时可增删节点 | 低,行为随环境漂移 | 插件式扩展,需日志留痕 |
链的隐性风险在「静默失败」:如果所有节点都选择放过,请求既没被处理也没报错。养成习惯——链尾必须有兜底节点,或者像示例那样明确抛出异常。
责任链与装饰器都涉及「层层包裹」,区别在控制流:装饰器通常每层都执行并层层返回,责任链是某一层处理后即终止。混用两种语义会让调试变得困难。