责任链模式属于行为型设计模式的一种,核心思想是让多个处理对象组成一条链,请求沿着这条链依次传递,直到有对象处理该请求为止。这种模式可以将请求的发送者和接收者解耦,避免发送者直接依赖具体的处理类,让代码结构更加灵活,后续扩展处理逻辑也更加方便。

责任链模式的核心角色
在C++实现责任链模式时,通常会包含以下几个核心角色:
- 抽象处理者:定义处理请求的接口,同时包含设置下一个处理者的方法,以及处理请求的核心方法声明。
- 具体处理者:实现抽象处理者的接口,完成具体的请求处理逻辑,如果当前对象无法处理请求,就将请求传递给下一个处理者。
- 请求对象:封装请求的相关信息,比如请求类型、请求参数等,方便处理者获取请求内容。
基础实现示例
下面通过一个审批流程的例子来演示责任链模式的C++实现,场景是不同级别的审批人处理不同金额的请假申请。
1. 定义请求类
首先定义封装请假申请信息的请求类:
#include <iostream>
#include <string>
// 请假请求类
class LeaveRequest {
private:
std::string name; // 请假人姓名
int days; // 请假天数
public:
LeaveRequest(const std::string& n, int d) : name(n), days(d) {}
std::string getName() const {
return name;
}
int getDays() const {
return days;
}
};
2. 定义抽象处理者
抽象处理者定义处理请求的接口和下一个处理者的引用:
// 抽象审批人(抽象处理者)
class Approver {
protected:
Approver* nextApprover; // 下一个处理者
std::string title; // 审批人职位
public:
Approver(const std::string& t) : nextApprover(nullptr), title(t) {}
// 设置下一个处理者
void setNext(Approver* next) {
nextApprover = next;
}
// 处理请求的抽象方法
virtual void handleRequest(const LeaveRequest& request) = 0;
virtual ~Approver() {}
};
3. 实现具体处理者
分别实现组长、经理、总监三个具体审批人,对应不同的请假天数处理权限:
// 组长审批(具体处理者1:处理3天以内的请假)
class GroupLeader : public Approver {
public:
GroupLeader() : Approver("组长") {}
void handleRequest(const LeaveRequest& request) override {
if (request.getDays() <= 3) {
std::cout << title << "审批了" << request.getName() << "的"
<< request.getDays() << "天请假申请" << std::endl;
} else if (nextApprover != nullptr) {
// 无法处理,传递给下一个处理者
nextApprover->handleRequest(request);
} else {
std::cout << "没有更高权限的审批人,请求无法处理" << std::endl;
}
}
};
// 部门经理审批(具体处理者2:处理3-7天的请假)
class DepartmentManager : public Approver {
public:
DepartmentManager() : Approver("部门经理") {}
void handleRequest(const LeaveRequest& request) override {
if (request.getDays() > 3 && request.getDays() <= 7) {
std::cout << title << "审批了" << request.getName() << "的"
<< request.getDays() << "天请假申请" << std::endl;
} else if (nextApprover != nullptr) {
nextApprover->handleRequest(request);
} else {
std::cout << "没有更高权限的审批人,请求无法处理" << std::endl;
}
}
};
// 总监审批(具体处理者3:处理7天以上的请假)
class Director : public Approver {
public:
Director() : Approver("总监") {}
void handleRequest(const LeaveRequest& request) override {
if (request.getDays() > 7) {
std::cout << title << "审批了" << request.getName() << "的"
<< request.getDays() << "天请假申请" << std::endl;
} else if (nextApprover != nullptr) {
nextApprover->handleRequest(request);
} else {
std::cout << "没有更高权限的审批人,请求无法处理" << std::endl;
}
}
};
4. 组装责任链并测试
在客户端代码中组装处理链,发起请求测试:
int main() {
// 创建处理者对象
Approver* groupLeader = new GroupLeader();
Approver* deptManager = new DepartmentManager();
Approver* director = new Director();
// 组装责任链:组长->部门经理->总监
groupLeader->setNext(deptManager);
deptManager->setNext(director);
// 创建三个不同天数的请假请求
LeaveRequest req1("张三", 2);
LeaveRequest req2("李四", 5);
LeaveRequest req3("王五", 10);
// 发起请求,都从链头开始传递
std::cout << "处理请求1:" << std::endl;
groupLeader->handleRequest(req1);
std::cout << "n处理请求2:" << std::endl;
groupLeader->handleRequest(req2);
std::cout << "n处理请求3:" << std::endl;
groupLeader->handleRequest(req3);
// 释放内存
delete groupLeader;
delete deptManager;
delete director;
return 0;
}
上述代码运行后,会分别输出不同请假请求对应的审批结果,请求会沿着组装好的责任链传递,直到被能够处理的处理者处理。
责任链模式的使用注意事项
- 需要合理设置责任链的长度,避免链过长导致请求处理效率下降,同时要避免出现循环引用的情况。
- 不是所有请求都必须被处理,如果链末尾的处理者也无法处理,需要做好默认的兜底处理,避免请求被丢弃没有响应。
- 如果处理逻辑比较复杂,也可以在抽象处理者中实现默认的处理方法,具体处理者根据需要重写对应逻辑,减少重复代码。
适用场景
当有多个对象可以处理同一个请求,但具体由哪个对象处理需要运行时判断时,或者需要动态指定处理对象集合时,都可以考虑使用责任链模式。比如日志分级处理、权限校验链、请求过滤等场景,使用该模式都能有效降低代码耦合度。