1、责任链模式概述:
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它让多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。链上的对象将请求沿着链传递,直到某个对象处理它为止。在责任链模式中,每个处理器都包含对下一个处理器的引用。请求从链上的第一个处理器开始,直到某个处理器处理请求为止。
2、责任链模式的适用场景:
- 当有多个对象可以处理一个请求,但是具体哪个对象处理该请求是在运行时动态决定的。
- 当想在不明确指定接收者的情况下,向多个对象中的一个提交请求。
- 当处理请求的对象集合应该动态指定时。
3、责任链模式的优点:
- 降低耦合度:责任链模式将请求的发送者和接收者解耦,使得发送者不需要知道哪个接收者处理请求,接收者也不需要知道请求的发送者。
- 增强了给对象指派职责的灵活性:可以在运行时动态地修改处理器的顺序或者添加新的处理器。
- 以合理的方式组织处理器:责任链模式提供了一种将处理器组织成链的方式,使得请求的处理更加清晰和有条理。
举例:一个客户支持系统,不同级别的客服人员处理不同级别的问题。问题首先由一线客服处理,如果无法解决则传递给二线客服,依次类推。这种场景就可以使用责任链模式实现,每个客服人员是链上的一个处理器,他们按照问题的级别处理请求。
4、责任链模式的缺点:
- 链过长可能导致性能问题:如果责任链过长,请求在链上的传递可能会导致处理延迟,从而影响程序性能。
- 不保证请求一定被处理:因为请求在链上传递,如果没有合适的处理器处理请求,请求就会被丢弃。这需要开发者在设计时特别注意。
举例:在一个日志记录系统中,根据日志的级别,有不同的日志记录器处理。譬如:DEBUG、INFO、ERROR。如果责任链上没有配置处理ERROR级别的记录器,那么ERROR日志将不会被处理。
5、用C++实现一个责任链模式例子:
#include <iostream>
#include <memory>
// 抽象处理器类
class Handler {
public:
virtual ~Handler() = default;
void set_next_handler(std::shared_ptr<Handler> handler) {
next_handler = handler;
}
virtual void handle_request(int request) {
if (next_handler != nullptr) {
next_handler->handle_request(request);
}
}
protected:
std::shared_ptr<Handler> next_handler;
};
// 具体处理器类:处理小于10的请求
class ConcreteHandler1 : public Handler {
public:
void handle_request(int request) override {
if (request < 10) {
std::cout << "ConcreteHandler1 handled request: " << request << std::endl;
} else if (next_handler != nullptr) {
next_handler->handle_request(request);
}
}
};
// 具体处理器类:处理大于等于10且小于20的请求
class ConcreteHandler2 : public Handler {
public:
void handle_request(int request) override {
if (request >= 10 && request < 20) {
std::cout << "ConcreteHandler2 handled request: " << request << std::endl;
} else if (next_handler != nullptr) {
next_handler->handle_request(request);
}
}
};
int main() {
std::shared_ptr<Handler> handler1 = std::make_shared<ConcreteHandler1>();
std::shared_ptr<Handler> handler2 = std::make_shared<ConcreteHandler2>();
handler1->set_next_handler(handler2);
// 测试请求
handler1->handle_request(5);
handler1->handle_request(15);
handler1->handle_request(25);
return 0;
}
在这个示例中,我们首先定义了一个抽象的处理器类Handler,它包含了一个指向下一个处理器的指针。然后我们创建了两个具体的处理器类:ConcreteHandler1 和 ConcreteHandler2,它们分别处理不同范围的请求。
在main函数中,我们创建了两个具体处理器对象,并将它们连接起来。然后我们测试了不同的请求,可以看到这些请求会被相应的处理器处理。