责任链模式(Chain of Responsibility):请求沿链传递,直到有人处理
更新时间:2026-08-25。本文按"先看不用模式的困境 → 再用模式重构 → 类图对比分析"的结构,论述责任链模式。可运行代码:demos/design-patterns/chain-of-responsibility。
一、问题场景:一个请求有多个候选处理者,条件动态
审批流(<1 万主管、<10 万总监、以上 VP)、日志分级(DEBUG/INFO/ERROR)、过滤器链(认证→限流→日志)、异常降级链。处理者的顺序与集合可能在运行时变化。
二、不使用模式:if/else 层层判断
cpp
std::string approve(double amount) {
if (amount < 10000) return "主管";
else if (amount < 100000) return "总监";
else if (amount < 1000000) return "VP";
else return "董事会";
}
// 审批规则变(阈值/新层级):改这一个函数,且无法动态调整顺序| 缺陷 | 说明 |
|---|---|
| 违反 OCP | 加处理者 = 改判断函数 |
| 条件与处理耦合 | 条件逻辑写死在调用点 |
| 无法动态调整 | 链的顺序/成员运行时不可变 |
| 复用性差 | 别的场景想复用"总监审批"只能复制 |
不使用模式的类图

三、使用模式:处理者串成链,请求自动下传
责任链模式定义处理者抽象(handle() 处理或 next() 传给下家),各处理者持有下一个处理者引用;请求从链头进入,每个处理者决定"自己处理还是下传"——链的组成在运行时任意装配。
cpp
// approval_chain.h
class Approver { // 处理者抽象
public:
Approver* next_ = nullptr;
void setNext(Approver* n) { next_ = n; }
virtual std::string approve(double amount) {
if (next_) return next_->approve(amount); // 默认:下传
return "无人处理";
}
virtual ~Approver() = default;
};
class Manager : public Approver {
public:
std::string approve(double amount) override {
if (amount < 10000) return "主管";
return Approver::approve(amount); // 超限下传
}
};
class Director : public Approver {
public:
std::string approve(double amount) override {
if (amount < 100000) return "总监";
return Approver::approve(amount);
}
};
class VP : public Approver { /* < 100 万 → VP,否则下传 */ };
// 运行时组装链
Manager mgr; Director dir; VP vp;
mgr.setNext(&dir); dir.setNext(&vp); // 链可任意增删/调序
std::cout << mgr.approve(50000); // 主管不接 → 总监接使用模式的类图

四、类图对比与分析
| 维度 | 不使用(if/else 链) | 使用责任链 |
|---|---|---|
| 加处理者 | 改判断函数 | 新类 + 挂到链上 |
| 顺序调整 | 改代码 | 运行时 setNext 重排 |
| 条件与处理 | 耦合在一处 | 每个处理者自带条件 |
| 复用 | 无法单独复用 | 单个处理者可独立装配到别的链 |
| 未处理情形 | 兜底分支 | 链尾兜底处理者 |
分析结论:责任链把"条件判断 + 处理"拆散到链上各个处理者,请求在链上"游走"直到被处理。代价是请求可能整链走完(性能上链长 × 单次判断)、处理结果不透明(谁处理的要调试才知道)。本仓库性能视角:链上的每个节点是一次函数调用,长链在热点路径要评估。
五、适用边界
| 适用 | 不适用 |
|---|---|
| 多个候选处理者、条件动态 | 处理者固定且少(if/else 更直接) |
| 链的组成需运行时装配 | 无条件传递、总是同一处理者(责任链是绕圈) |
| 过滤器/拦截器/审批流场景 | 需要对链上每个节点都处理(那是管道模式) |
与装饰器的区别:责任链"传递请求"(要么处理要么下传,最终一个处理);装饰器"逐层增强"(每层都执行并继续)。责任链关心"谁接单",装饰器关心"叠加什么"。
一句话总结
责任链模式把候选处理者串成链,请求从链头进入、沿链传递直到有人处理——处理者集合与顺序运行时可装配,加处理者不再改旧逻辑;代价是请求可能遍历整链、处理者归属不透明,链长在热点路径上要克制。