1. 责任链模式初探:从生活场景到代码实现
作为一名长期奋战在C++开发一线的程序员,我最近重读了经典著作《Head First设计模式》。这本书虽然以Java为例,但设计模式的思想是语言无关的。今天我想分享其中责任链模式(Chain of Responsibility Pattern)的C++实现,以及我在实际项目中的应用心得。
想象一下公司请假流程:1天内小组长批,2-3天部门经理批,4天以上总经理批。这种"层层上报"的机制正是责任链模式的完美体现。在软件设计中,我们经常遇到类似场景——一个请求需要经过多个对象的检查和处理,每个对象只关心自己职责范围内的部分。
提示:责任链模式特别适合处理审批流程、事件过滤、异常处理等场景,它能有效解耦请求发送者和接收者。
2. 模式结构与核心思想
2.1 责任链的三大角色
责任链模式包含三个核心组件:
-
Handler(抽象处理者):定义处理请求的接口,通常包含:
- 处理请求的抽象方法
- 指向后继处理者的引用
- 设置后继者的方法
-
ConcreteHandler(具体处理者):实现处理接口,包含:
- 自身处理逻辑的判断条件
- 不能处理时的转发逻辑
- 具体的处理实现
-
Client(客户端):负责:
- 创建处理链
- 设置处理者的后继关系
- 发起请求
2.2 UML类图解析

从UML图中可以看到:
- Approver是抽象处理者,定义了setNextApprover和approve接口
- 三个具体处理者继承自Approver
- 客户端负责构建链式关系
这种结构让每个处理者只需关注自己的职责范围,实现了"单一职责原则"。
3. C++实现详解
3.1 基础类设计
首先定义请假请求类,封装请假数据:
cpp复制class LeaveRequest {
public:
LeaveRequest(string name, int days)
: m_name(name), m_days(days) {}
string getName() const { return m_name; }
int getDays() const { return m_days; }
private:
string m_name; // 请假人
int m_days; // 请假天数
};
3.2 抽象处理者实现
抽象审批者类定义了责任链的核心结构:
cpp复制class Approver {
public:
Approver(string name) : m_name(name) {}
// 设置后继审批者(构建责任链)
void setNextApprover(Approver* next) {
m_nextApprover = next;
}
// 抽象审批方法(核心)
virtual void approve(LeaveRequest* request) = 0;
virtual ~Approver() = default;
protected:
string m_name; // 审批者名称
Approver* m_nextApprover = nullptr; // 后继审批者
};
3.3 具体处理者实现
三个具体审批者实现审批逻辑:
cpp复制// 小组长:处理1天及以内请假
class GroupLeader : public Approver {
public:
GroupLeader(string name) : Approver(name) {}
void approve(LeaveRequest* request) override {
if (request->getDays() <= 1) {
cout << "小组长" << m_name << "审批:"
<< request->getName() << "请假"
<< request->getDays() << "天,批准!" << endl;
}
else if (m_nextApprover != nullptr) {
cout << "小组长" << m_name << ":请假"
<< request->getDays()
<< "天,超出权限,转交部门经理..." << endl;
m_nextApprover->approve(request);
}
else {
cout << "小组长" << m_name
<< ":无更高审批者,请假失败!" << endl;
}
}
};
// 部门经理:处理2-3天请假
class DepartmentManager : public Approver {
public:
DepartmentManager(string name) : Approver(name) {}
void approve(LeaveRequest* request) override {
if (request->getDays() >= 2 && request->getDays() <= 3) {
cout << "部门经理" << m_name << "审批:"
<< request->getName() << "请假"
<< request->getDays() << "天,批准!" << endl;
}
else if (m_nextApprover != nullptr) {
cout << "部门经理" << m_name << ":请假"
<< request->getDays()
<< "天,超出权限,转交总经理..." << endl;
m_nextApprover->approve(request);
}
else {
cout << "部门经理" << m_name
<< ":无更高审批者,请假失败!" << endl;
}
}
};
// 总经理:处理4天及以上请假
class GeneralManager : public Approver {
public:
GeneralManager(string name) : Approver(name) {}
void approve(LeaveRequest* request) override {
if (request->getDays() >= 4) {
cout << "总经理" << m_name << "审批:"
<< request->getName() << "请假"
<< request->getDays() << "天,批准!" << endl;
}
else {
cout << "总经理" << m_name
<< ":请假天数不符合权限范围,审批失败!" << endl;
}
}
};
3.4 客户端使用示例
cpp复制int main() {
// 1. 创建各审批者
Approver* groupLeader = new GroupLeader("张三");
Approver* deptManager = new DepartmentManager("李四");
Approver* genManager = new GeneralManager("王五");
// 2. 构建责任链:小组长 → 部门经理 → 总经理
groupLeader->setNextApprover(deptManager);
deptManager->setNextApprover(genManager);
// 3. 发起不同的请假请求
LeaveRequest* req1 = new LeaveRequest("小明", 1); // 小组长处理
LeaveRequest* req2 = new LeaveRequest("小红", 3); // 部门经理处理
LeaveRequest* req3 = new LeaveRequest("小刚", 5); // 总经理处理
// 4. 从链头(小组长)提交请求
groupLeader->approve(req1);
cout << "------------------------" << endl;
groupLeader->approve(req2);
cout << "------------------------" << endl;
groupLeader->approve(req3);
// 释放资源
delete req1;
delete req2;
delete req3;
delete groupLeader;
delete deptManager;
delete genManager;
return 0;
}
运行结果:
code复制小组长张三审批:小明请假1天,批准!
------------------------
小组长张三:请假3天,超出权限,转交部门经理...
部门经理李四审批:小红请假3天,批准!
------------------------
小组长张三:请假5天,超出权限,转交部门经理...
部门经理李四:请假5天,超出权限,转交总经理...
总经理王五审批:小刚请假5天,批准!
4. 模式优势与适用场景
4.1 责任链的五大优势
- 解耦请求发送者和接收者:发送者无需知道具体由谁处理
- 动态调整责任链:可运行时增减处理者或改变顺序
- 单一职责原则:每个处理者只关注自身职责
- 开闭原则:新增处理者无需修改现有代码
- 灵活组合:可以构建树形、环形等复杂责任链
4.2 典型应用场景
- 多级审批系统(如请假、报销)
- 事件处理系统(如GUI事件传递)
- 异常处理机制(如try-catch块)
- 过滤器链(如Web请求过滤)
- 日志记录系统(不同级别日志不同处理)
5. 实战经验与陷阱规避
5.1 性能优化技巧
- 短路处理:某些场景下找到合适处理者后可终止链
- 缓存处理者:频繁使用的链可以考虑缓存处理结果
- 并行处理:无先后顺序要求的处理可以并行化
5.2 常见问题及解决方案
| 问题 | 解决方案 |
|---|---|
| 循环引用 | 添加链构建验证逻辑 |
| 性能瓶颈 | 限制链长度或优化处理逻辑 |
| 请求丢失 | 设置默认处理者或日志记录 |
| 调试困难 | 添加请求追踪标识 |
5.3 内存管理注意事项
在C++实现中要特别注意:
- 明确所有权关系,避免内存泄漏
- 可以使用智能指针管理处理者生命周期
- 考虑使用对象池模式复用处理者实例
6. 扩展思考与进阶应用
6.1 责任链的变体模式
- 拦截过滤器模式:在Web框架中常见,每个过滤器处理请求后决定是否继续
- 管道-过滤器模式:每个处理者都对请求进行某种转换
- 装饰器模式:与责任链类似,但目的是添加功能而非处理请求
6.2 与其他模式的结合
- 组合模式:构建树形责任链
- 策略模式:动态更换处理逻辑
- 观察者模式:实现处理结果的通知机制
在实际项目中,我经常将责任链模式用于插件系统的消息处理。每个插件作为责任链的一个环节,可以处理或转发系统消息。这种设计让系统具有极好的扩展性——新增功能只需添加新的插件处理者,完全不影响现有代码。
最后分享一个实用技巧:在复杂系统中,可以为责任链添加监控中间件,记录请求在链中的流转情况,这对调试和性能分析非常有帮助。