C++设计模式之行为型模式:职责链模式(Chain of Responsibility) - 实践
职责链模式(Chain of Responsibility)是行为型设计模式的一种,它通过将请求的发送者与接收者解耦,使多个接收者(处理者)组成一条链,请求在链上传递,直到被某个处理者处理。此种模式避免了请求发送者与具体处理者的直接耦合,允许动态调整处理链。
一、核心思想与角色
“就是职责链模式的核心请求沿链传递,谁能处理谁处理”,凭借构建处理者链条实现请求的分发。其核心角色如下:
角色名称 | 核心职责 |
---|---|
抽象处理者(Handler) | 定义处理请求的接口,包含一个指向后继处理者的引用,声明处理请求的方法。 |
具体处理者(ConcreteHandler) | 实现抽象处理者接口,判断自身是否能处理请求:能处理则处理,否则将请求转发给后继者。 |
客户端(Client) | 创建处理者链条,并向链的第一个处理者发送请求,无需关心具体谁处理了请求。 |
核心思想:将多个处理者串联成链,请求从链的起点开始传递,每个处理者自行决定是否处理请求或转发给下一个处理者,从而实现请求与处理的解耦。
二、实现示例(请假审批环境)
假设公司的请假审批流程为:
- 请假≤1天:组长审批
- 1天<请假≤3天:部门经理审批
- 3天<请假≤7天:总监审批
- 请假>7天:总经理审批
采用职责链模式可灵活构建审批流程:
#include <iostream>#include <string>// 请假请求class LeaveRequest {private:std::string employeeName; // 员工姓名int days; // 请假天数public:LeaveRequest(const std::string& name, int d): employeeName(name), days(d) {}std::string getEmployeeName() const { return employeeName; }int getDays() const { return days; }};// 1. 抽象处理者:审批者class Approver {protected:Approver* nextApprover; // 后继审批者(职责链的下一个节点)public:// 构造函数:初始化后继审批者Approver(Approver* next) : nextApprover(next) {}virtual ~Approver() {// 递归释放整条链(避免内存泄漏)delete nextApprover;nextApprover = nullptr;}// 纯虚方法:处理请假请求virtual void processRequest(const LeaveRequest& request) = 0;};// 2. 具体处理者1:组长(处理≤1天的请假)class TeamLeader : public Approver {public:TeamLeader(Approver* next) : Approver(next) {}void processRequest(const LeaveRequest& request) override {if (request.getDays() <= 1) {// 能处理:直接审批std::cout << "组长审批了" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;} else if (nextApprover) {// 不能处理:转发给下一个审批者nextApprover->processRequest(request);} else {// 无后继者:无法审批std::cout << "无人能审批" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;}}};// 2. 具体处理者2:部门经理(处理1~3天的请假)class DepartmentManager : public Approver {public:DepartmentManager(Approver* next) : Approver(next) {}void processRequest(const LeaveRequest& request) override {if (request.getDays() > 1 && request.getDays() <= 3) {std::cout << "部门经理审批了" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;} else if (nextApprover) {nextApprover->processRequest(request);} else {std::cout << "无人能审批" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;}}};// 2. 具体处理者3:总监(处理3~7天的请假)class Director : public Approver {public:Director(Approver* next) : Approver(next) {}void processRequest(const LeaveRequest& request) override {if (request.getDays() > 3 && request.getDays() <= 7) {std::cout << "总监审批了" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;} else if (nextApprover) {nextApprover->processRequest(request);} else {std::cout << "无人能审批" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;}}};// 2. 具体处理者4:总经理(处理>7天的请假)class GeneralManager : public Approver {public:GeneralManager(Approver* next) : Approver(next) {}void processRequest(const LeaveRequest& request) override {if (request.getDays() > 7) {std::cout << "总经理审批了" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;} else if (nextApprover) {nextApprover->processRequest(request);} else {std::cout << "无人能审批" << request.getEmployeeName()<< "的" << request.getDays() << "天请假" << std::endl;}}};// 客户端代码:构建审批链并发起请求int main() {// 构建职责链:组长 → 部门经理 → 总监 → 总经理Approver* chain = new TeamLeader(new DepartmentManager(new Director(new GeneralManager(nullptr) // 链的末尾)));// 发起不同天数的请假请求LeaveRequest req1("张三", 1); // 组长审批LeaveRequest req2("李四", 2); // 部门经理审批LeaveRequest req3("王五", 5); // 总监审批LeaveRequest req4("赵六", 10); // 总经理审批LeaveRequest req5("钱七", 0); // 组长审批(特殊情况)chain->processRequest(req1);chain->processRequest(req2);chain->processRequest(req3);chain->processRequest(req4);chain->processRequest(req5);// 释放链条(会递归释放所有处理者)delete chain;return 0;}
三、代码解析
请求对象(LeaveRequest):封装请假信息(员工姓名、天数),作为处理者的处理参数。
抽象处理者(Approver):
- 包含
nextApprover
指针,指向链中的下一个处理者。 - 声明纯虚方法
processRequest()
,定义处理请求的接口。 - 析构函数递归释放整条链,避免内存泄漏。
- 包含
具体处理者:
每个处理者(TeamLeader
、DepartmentManager
等)实现processRequest()
方法,根据自身职责范围决定是否处理请求:- 若请求在自身处理范围内(如组长处理≤1天的请假),则直接处理。
- 若不在范围内且存在后继处理者,则转发请求(
nextApprover->processRequest(request)
)。 - 若不在范围内且无后继者,则提示无法处理。
客户端构建链条:
客户端通过嵌套构造函数创建处理者链条(组长→部门经理→总监→总经理),并向链的第一个处理者发送请求,无需关心具体由谁处理。
四、核心优势与适用场景
优势
- 解耦请求与处理:请求发送者无需知道谁处理了请求,处理者也无需知道请求的来源,降低耦合度。
- 动态调整链条:可通过增删处理者或改变顺序动态调整处理流程(如临时跳过部门经理审批)。
- 单一职责:每个处理者只负责自己范围内的请求,符合单一职责原则。
- 灵活性:新处理者可随时加入链中,无需修改现有代码(符合开闭原则)。
适用场景
- 存在多个处理者,且处理范围明确:如审批流程、日志级别处理(DEBUG→INFO→WARN→ERROR)。
- 请求的处理者不确定:请求发送时不知道谁会处理,需动态决定。
- 应该动态调整处理流程:如根据业务规则临时改变处理顺序或增减处理步骤。
五、与其他模式的区别
模式 | 核心差异点 |
---|---|
职责链模式 | 请求沿链传递,由第一个能处理的对象处理,强调“请求分发与传递”。 |
命令模式 | 将请求封装为对象,可参数化、队列化请求,强调“请求的封装与执行”。 |
观察者模式 | 一个对象改变时通知多个观察者,所有观察者都会处理通知,而非选择一个处理。 |
状态模式 | 对象状态变化时改变行为,处理逻辑与状态绑定,而非沿链传递。 |
六、实践建议
- 明确处理范围:每个处理者的职责范围应清晰,避免重叠或遗漏导致请求无法处理。
- 设置默认处理者:在链的末尾添加默认处理者,确保所有请求都能被处理(或给出明确提示)。
- 避免过长链条:链条过长可能导致请求传递效率低,可利用分组或层级优化。
- 承受动态调整:设计时考虑允许运行时修改链条(如添加、移除或重新排序处理者)。
职责链模式的核心价值在于“灵活分发请求,解耦发送者与处理者”。它利用构建处理者链条,使请求能自动找到合适的处理者,同时协助动态调整处理流程,是处理具有层级关系或多步骤审批场景的理想选择。