责任链模式
责任链模式是一种行为设计模式,用于处理请求,允许多个对象通过链式结构依次处理同一请求,直到请求被处理或链结束。以下是该模式的详细分析:
核心思想
- 链式处理:将处理请求的对象串联成一条链,每个对象都有机会处理请求。
- 动态传递:如果一个对象无法处理请求,它会将请求传递给链中的下一个对象,直到请求被处理或链结束。
优点
- 职责分离:每个处理者专注于自己的职责,系统结构清晰。
- 灵活扩展:新增处理者只需修改链的结构,无需改变现有代码。
- 动态处理:请求处理流程可根据实际需求动态调整。
缺点
- 处理延迟:链长可能导致处理时间增加。
- 复杂性:链的设计和维护可能较复杂,需确保正确终止。
应用场景
- 审批流程:如请假、报销等,根据权限层级传递请求。
- 权限控制:不同权限用户对资源的访问控制。
- 日志系统:不同级别的日志由不同的处理器处理。
- 异常处理:根据异常类型传递给合适的处理程序。
示例
请假示例
#include <iostream>
using namespace std;
class Handler {
public:
virtual ~Handler() = default;
virtual void handleRequest(int days) = 0;
void setNext(Handler* next) {
this->next = next;
}
protected:
Handler* next = nullptr;
};
class Manager : public Handler {
public:
void handleRequest(int days) override {
if (days <= 3) {
cout << "经理处理了" << days << "天的请假。" << endl;
} else if (next != nullptr) {
next->handleRequest(days);
} else {
cout << "请假天数过多,无法处理。" << endl;
}
}
};
class Director : public Handler {
public:
void handleRequest(int days) override {
if (days <= 7) {
cout << "总监处理了" << days << "天的请假。" << endl;
} else if (next != nullptr) {
next->handleRequest(days);
} else {
cout << "请假天数过多,无法处理。" << endl;
}
}
};
class CEO : public Handler {
public:
void handleRequest(int days) override {
if (days <= 15) {
cout << "总经理处理了" << days << "天的请假。" << endl;
} else {
cout << "请假天数过多,无法处理。" << endl;
}
}
};
int main() {
Manager* manager = new Manager();
Director* director = new Director();
CEO* ceo = new CEO();
manager->setNext(director);
director->setNext(ceo);
// 测试不同的请假天数
manager->handleRequest(2); // 经理处理
manager->handleRequest(5); // 经理传给总监
manager->handleRequest(10); // 经理→总监→总经理
delete manager;
delete director;
delete ceo;
return 0;
}
代码解释:
- Handler类:这是一个抽象类,定义了处理请求的方法
handleRequest
和设置下一个处理者的方法setNext
。 - 具体处理者类:
- Manager类:处理3天以内的请假,超过则传递给下一个处理者。
- Director类:处理7天以内的请假,超过则传递给下一个处理者。
- CEO类:处理15天以内的请假,超过则无法处理。
- 客户端代码:
- 创建各个处理者的实例。
- 将处理者连接成一个链:Manager -> Director -> CEO。
- 测试不同的请假天数,观察请求如何在链中传递。
输出结果:
经理处理了2天的请假。
总监处理了5天的请假。
总经理处理了10天的请假。
注意事项:
- 内存管理:使用了
new
动态分配内存,记得在析构时使用delete
释放内存,避免内存泄漏。在实际项目中,建议使用智能指针(如unique_ptr
或shared_ptr
)来管理内存。 - 链路构建:确保处理者的链路正确构建,避免循环引用导致死循环。
- 可扩展性:可以根据需要添加更多的处理者到链中,而不需要修改现有代码,体现出良好的扩展性。
这个示例展示了责任链模式的基本实现和应用场景,能够帮助处理类似的需求,如审批流程、日志记录等。
日志处理系统示例
日志系统通常会有多个级别,如 DEBUG、INFO、WARNING、ERROR,不同级别的日志由不同的处理器负责。
#include <iostream>
enum LogLevel { DEBUG, INFO, WARNING, ERROR };
// 抽象处理者类
class Logger {
protected:
Logger* next;
public:
Logger() : next(nullptr) {}
void setNext(Logger* nextLogger) { next = nextLogger; }
void logMessage(LogLevel level, const std::string& message) {
if (canHandle(level)) {
write(message);
}
if (next) {
next->logMessage(level, message);
}
}
virtual bool canHandle(LogLevel level) = 0;
virtual void write(const std::string& message) = 0;
};
// 具体处理者:DebugLogger
class DebugLogger : public Logger {
public:
bool canHandle(LogLevel level) override { return level == DEBUG; }
void write(const std::string& message) override {
std::cout << "[DEBUG] " << message << std::endl;
}
};
// 具体处理者:InfoLogger
class InfoLogger : public Logger {
public:
bool canHandle(LogLevel level) override { return level == INFO; }
void write(const std::string& message) override {
std::cout << "[INFO] " << message << std::endl;
}
};
// 具体处理者:ErrorLogger
class ErrorLogger : public Logger {
public:
bool canHandle(LogLevel level) override { return level == ERROR; }
void write(const std::string& message) override {
std::cout << "[ERROR] " << message << std::endl;
}
};
// 测试代码
int main() {
DebugLogger debugLogger;
InfoLogger infoLogger;
ErrorLogger errorLogger;
debugLogger.setNext(&infoLogger);
infoLogger.setNext(&errorLogger);
debugLogger.logMessage(DEBUG, "This is a debug message.");
debugLogger.logMessage(INFO, "This is an info message.");
debugLogger.logMessage(ERROR, "This is an error message.");
}
运行结果:
[DEBUG] This is a debug message.
[INFO] This is an info message.
[ERROR] This is an error message.
事件处理系统(UI 组件事件分发)
在 GUI 应用中,事件通常需要从子组件传递到父组件,直到找到合适的处理者。例如,一个按钮点击事件可能会被自身处理,或者传递给窗口管理器处理。
#include <iostream>
// 抽象基类
class UIComponent {
protected:
UIComponent* parent;
public:
UIComponent(UIComponent* p = nullptr) : parent(p) {}
virtual void handleEvent(const std::string& event) {
if (parent) {
parent->handleEvent(event);
} else {
std::cout << "Unhandled event: " << event << std::endl;
}
}
};
// 具体处理者:按钮
class Button : public UIComponent {
public:
using UIComponent::UIComponent;
void handleEvent(const std::string& event) override {
if (event == "Click") {
std::cout << "Button handled Click event" << std::endl;
} else {
UIComponent::handleEvent(event);
}
}
};
// 具体处理者:窗口
class Window : public UIComponent {
public:
using UIComponent::UIComponent;
void handleEvent(const std::string& event) override {
if (event == "Resize") {
std::cout << "Window handled Resize event" << std::endl;
} else {
UIComponent::handleEvent(event);
}
}
};
// 测试代码
int main() {
Window mainWindow;
Button button(&mainWindow); // 按钮的父组件是窗口
button.handleEvent("Click"); // 由 Button 处理
button.handleEvent("Resize"); // 由 Window 处理
button.handleEvent("Unknown"); // 未处理的事件
}
运行结果:
Button handled Click event
Window handled Resize event
Unhandled event: Unknown
责任链处理用户请求(权限系统)
在权限管理系统中,请求可能需要多个级别的审批,如 普通员工 -> 经理 -> 总经理。
#include <iostream>
// 处理者基类
class Approver {
protected:
Approver* next;
public:
Approver() : next(nullptr) {}
void setNext(Approver* n) { next = n; }
virtual void processRequest(int amount) {
if (next) {
next->processRequest(amount);
} else {
std::cout << "Request for $" << amount << " was denied.\n";
}
}
};
// 具体处理者:经理
class Manager : public Approver {
public:
void processRequest(int amount) override {
if (amount <= 1000) {
std::cout << "Manager approved $" << amount << " request.\n";
} else {
Approver::processRequest(amount);
}
}
};
// 具体处理者:总经理
class GeneralManager : public Approver {
public:
void processRequest(int amount) override {
if (amount <= 5000) {
std::cout << "General Manager approved $" << amount << " request.\n";
} else {
Approver::processRequest(amount);
}
}
};
// 具体处理者:CEO
class CEO : public Approver {
public:
void processRequest(int amount) override {
if (amount <= 10000) {
std::cout << "CEO approved $" << amount << " request.\n";
} else {
std::cout << "Request for $" << amount << " needs a board meeting.\n";
}
}
};
// 测试代码
int main() {
Manager manager;
GeneralManager generalManager;
CEO ceo;
manager.setNext(&generalManager);
generalManager.setNext(&ceo);
manager.processRequest(500); // Manager 处理
manager.processRequest(2000); // General Manager 处理
manager.processRequest(7000); // CEO 处理
manager.processRequest(20000); // 需要董事会会议
}
运行结果:
Manager approved $500 request.
General Manager approved $2000 request.
CEO approved $7000 request.
Request for $20000 needs a board meeting.
注意事项
- 链的构建:确保每个处理者正确指向下一个处理者,避免循环或终止不当。
- 处理逻辑:明确每个处理者的职责,确保正确处理或传递请求。
总结
责任链模式适用于:
✅ 需要多个对象共同处理一个请求,但不确定具体哪个对象处理。
✅ 允许动态修改请求的处理链,提高灵活性。
✅ 降低耦合,使请求的发送者和接收者解耦。