责任链模式是一种设计模式,它将请求的发送者和接收者解耦,使得多个对象有机会处理该请求。它们被串成链,并沿着这条链传递请求,直到有对象处理它为止。
主要组成部分
1. Handler(处理者/处理器)接口 :
- 声明一个处理请求的方法,以及一个设置下一个处理者的方法。这个接口定义了请求处理程序必须要实现的基本结构。
2. ConcreteHandler(具体处理者/处理器)类:
-
每一个具体的处理者类都可以处理一类特定的请求,它实现了处理者接口。
-
如果该处理者认为自己不能处理请求,它应该将请求传递给链中的下一个处理者。
3. Client(客户端):
-
客户端创建并配置处理对象链。
-
客户端只需要将请求传递给链上的第一个处理者,而不需要知道具体由哪个处理者处理。
工作流程
-
请求发送:客户端将请求发给责任链的第一个处理者。
-
请求传递:请求在链条中向下传递,直到遇到处理该请求的处理者。
-
处理结束:当请求被处理后,链条结束执行。如果没有处理者处理该请求,通常可以定义一个默认的返回结果或处理方式。
示例代码详解
以下是前文代码的逐步分解,以说明责任链模式如何运作。
1. 处理者接口:
在处理者接口中,定义了两个关键方法:一个是用来设置下一个处理者的方法 `setNext()`,另一个是用来处理请求的方法 handleRequest()。
cpp
class Handler {
public:
virtual ~Handler() = default;
virtual void setNext(std::shared_ptr<Handler> nextHandler) = 0;
virtual void handleRequest(const std::string& request) = 0;
};
2. 具体处理者:
每一个具体处理者实现了处理者接口,通过实现 `handleRequest` 方法来处理其感兴趣的请求类型。如果不能处理请求,就将请求传递给下一个处理者。
cpp
class Secretary : public Handler {
private:
std::shared_ptr<Handler> nextHandler;
public:
void setNext(std::shared_ptr<Handler> nextHandler) override {
this->nextHandler = nextHandler;
}
void handleRequest(const std::string& request) override {
if (request == "low level request") {
std::cout << "Secretary handles the request.\n";
} else {
if (nextHandler) {
nextHandler->handleRequest(request);
}
}
}
};
// 其他具体处理者类似,处理它们特定的请求
// ConcreteHandler2
class Manager : public Handler {
private:
std::shared_ptr<Handler> nextHandler;
public:
void setNext(std::shared_ptr<Handler> nextHandler) override {
this->nextHandler = nextHandler;
}
void handleRequest(const std::string& request) override {
if (request == "mid level request") {
std::cout << "Manager handles the request.\n";
} else {
if (nextHandler) {
nextHandler->handleRequest(request);
}
}
}
};
// ConcreteHandler3
class Director : public Handler {
private:
std::shared_ptr<Handler> nextHandler;
public:
void setNext(std::shared_ptr<Handler> nextHandler) override {
this->nextHandler = nextHandler;
}
void handleRequest(const std::string& request) override {
if (request == "high level request") {
std::cout << "Director handles the request.\n";
} else {
if (nextHandler) {
nextHandler->handleRequest(request);
} else {
std::cout << "Request is left unhandled.\n";
}
}
}
};
**3. 创建责任链和处理请求:**在客户端代码中,链被建立起来,然后请求被传递下来。
cpp
int main() {
std::shared_ptr<Handler> secretary = std::make_shared<Secretary>();
std::shared_ptr<Handler> manager = std::make_shared<Manager>();
std::shared_ptr<Handler> director = std::make_shared<Director>();
// 创建链: Secretary -> Manager -> Director
secretary->setNext(manager);
manager->setNext(director);
// 处理请求
secretary->handleRequest("low level request");
secretary->handleRequest("mid level request");
secretary->handleRequest("high level request");
secretary->handleRequest("unknown request");
return 0;
}
责任链模式的优缺点
优点:
-
解耦合:请求的发送者和接收者解耦,不需要彼此知道的详细信息。
-
灵活性:可以灵活地新增或更改链上的处理者对象。
-
增强扩展性:通过继承`Handler`类,容易添加更多处理者。
缺点:
-
请求处理的不确定性:请求可能会沿着很长的链传递,而需要耗费大量的时间来找对的处理者。
-
可能没有处理:如果所有的处理者都没有处理请求,可能会导致请求被丢弃。
-
性能开销:长链可能会对性能造成影响,特别是在实时系统中。
应用场景
-
日志记录:可以有不同级别的日志记录处理者(如debug、info、warn、error等)。
-
操作流处理:如UI事件处理,某个处理者处理成功后返回。
-
权限管理:请求沿着职责链检查每个节点的权限,直到找到合适的处理者。
责任链模式是一种简单而有效的设计方式,特别适用于涉及到多个对象协作处理的系统。