职责链模式(Chain of Responsibility)是行为型设计模式的一种,它通过将请求的发送者与接收者解耦,使多个接收者(处理者)组成一条链,请求在链上传递,直到被某个处理者处理。这种模式避免了请求发送者与具体处理者的直接耦合,允许动态调整处理链。
一、核心思想与角色
职责链模式的核心是"请求沿链传递,谁能处理谁处理",通过构建处理者链条实现请求的分发。其核心角色如下:
角色名称 | 核心职责 |
---|---|
抽象处理者(Handler) | 定义处理请求的接口,包含一个指向后继处理者的引用,声明处理请求的方法。 |
具体处理者(ConcreteHandler) | 实现抽象处理者接口,判断自身是否能处理请求:能处理则处理,否则将请求转发给后继者。 |
客户端(Client) | 创建处理者链条,并向链的第一个处理者发送请求,无需关心具体谁处理了请求。 |
核心思想:将多个处理者串联成链,请求从链的起点开始传递,每个处理者自行决定是否处理请求或转发给下一个处理者,从而实现请求与处理的解耦。
二、实现示例(请假审批系统)
假设公司的请假审批流程为:
- 请假≤1天:组长审批
- 1天<请假≤3天:部门经理审批
- 3天<请假≤7天:总监审批
- 请假>7天:总经理审批
使用职责链模式可灵活构建审批流程:
cpp
#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)。
- 请求的处理者不确定:请求发送时不知道谁会处理,需动态决定。
- 需要动态调整处理流程:如根据业务规则临时改变处理顺序或增减处理步骤。
五、与其他模式的区别
模式 | 核心差异点 |
---|---|
职责链模式 | 请求沿链传递,由第一个能处理的对象处理,强调"请求分发与传递"。 |
命令模式 | 将请求封装为对象,可参数化、队列化请求,强调"请求的封装与执行"。 |
观察者模式 | 一个对象改变时通知多个观察者,所有观察者都会处理通知,而非选择一个处理。 |
状态模式 | 对象状态变化时改变行为,处理逻辑与状态绑定,而非沿链传递。 |
六、实践建议
- 明确处理范围:每个处理者的职责范围应清晰,避免重叠或遗漏导致请求无法处理。
- 设置默认处理者:在链的末尾添加默认处理者,确保所有请求都能被处理(或给出明确提示)。
- 避免过长链条:链条过长可能导致请求传递效率低,可通过分组或层级优化。
- 支持动态调整:设计时考虑允许运行时修改链条(如添加、移除或重新排序处理者)。
职责链模式的核心价值在于"灵活分发请求,解耦发送者与处理者"。它通过构建处理者链条,使请求能自动找到合适的处理者,同时支持动态调整处理流程,是处理具有层级关系或多步骤审批场景的理想选择。