职责链模式 (Chain of Responsibility)
职责链模式 是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。这些对象通过形成一条链,沿着这条链传递请求,直到有对象处理它为止。
意图
- 通过将请求的发送者与接收者解耦,动态地决定由哪个对象来处理请求。
- 使多个对象有机会处理请求,而不是由固定的对象处理。
使用场景
- 请求的处理者不确定:
- 在运行时,可能需要多个对象来处理请求,但具体的处理者在编译时无法确定。
- 需要动态组合请求处理的责任链:
- 希望将多个处理者按顺序动态排列。
- 减少耦合:
- 将请求的发送者和处理者解耦。
参与者角色
- 处理者接口 (Handler)
- 定义处理请求的方法,并保存对下一个处理者的引用。
- 具体处理者 (ConcreteHandler)
- 实现处理者接口,处理请求或将请求传递给下一个处理者。
- 客户端 (Client)
- 创建责任链,并向责任链中的第一个处理者发送请求。
示例代码
以下代码展示了职责链模式的实现,用于模拟用户请求的权限校验。系统中有三种责任:身份验证、权限验证和业务处理。
#include <iostream>
#include <memory>
#include <string>
// 处理者接口
class Handler {
protected:
std::shared_ptr<Handler> nextHandler; // 下一个处理者
public:
virtual ~Handler() = default;
// 设置下一个处理者
void setNext(std::shared_ptr<Handler> next) {
nextHandler = std::move(next);
}
// 处理请求的接口
virtual void handleRequest(const std::string& request) {
if (nextHandler) {
nextHandler->handleRequest(request); // 将请求传递给下一个处理者
}
}
};
// 具体处理者:身份验证
class AuthHandler : public Handler {
public:
void handleRequest(const std::string& request) override {
if (request == "auth") {
std::cout << "身份验证通过。
";
if (nextHandler) {
nextHandler->handleRequest(request); // 传递给下一个处理者
}
} else {
std::cout << "身份验证失败。
";
}
}
};
// 具体处理者:权限验证
class PermissionHandler : public Handler {
public:
void handleRequest(const std::string& request) override {
if (request == "auth") {
std::cout << "权限验证通过。
";
if (nextHandler) {
nextHandler->handleRequest(request); // 传递给下一个处理者
}
} else {
std::cout << "权限验证失败。
";
}
}
};
// 具体处理者:业务处理
class BusinessHandler : public Handler {
public:
void handleRequest(const std::string& request) override {
if (request == "auth") {
std::cout << "业务处理完成。
";
} else {
std::cout << "无法进行业务处理。
";
}
}
};
// 客户端代码
int main() {
// 创建处理者
auto authHandler = std::make_shared<AuthHandler>();
auto permissionHandler = std::make_shared<PermissionHandler>();
auto businessHandler = std::make_shared<BusinessHandler>();
// 构建责任链
authHandler->setNext(permissionHandler);
permissionHandler->setNext(businessHandler);
// 发送请求
std::cout << "发送请求:auth
";
authHandler->handleRequest("auth");
std::cout << "
发送请求:invalid
";
authHandler->handleRequest("invalid");
return 0;
}
代码解析
1. 处理者接口 (Handler)
- 定义了处理请求的接口
handleRequest
,并包含对下一个处理者的引用。 - 通过
setNext
方法设置链中的下一个处理者。
class Handler {
protected:
std::shared_ptr<Handler> nextHandler; // 下一个处理者
public:
virtual ~Handler() = default;
void setNext(std::shared_ptr<Handler> next) {
nextHandler = std::move(next);
}
virtual void handleRequest(const std::string& request) {
if (nextHandler) {
nextHandler->handleRequest(request); // 将请求传递给下一个处理者
}
}
};
2. 具体处理者 (AuthHandler, PermissionHandler, BusinessHandler)
AuthHandler
:- 验证请求是否通过身份认证。
PermissionHandler
:- 验证请求是否有权限。
BusinessHandler
:- 完成实际的业务逻辑处理。
class AuthHandler : public Handler {
public:
void handleRequest(const std::string& request) override {
if (request == "auth") {
std::cout << "身份验证通过。
";
if (nextHandler) {
nextHandler->handleRequest(request);
}
} else {
std::cout << "身份验证失败。
";
}
}
};
3. 客户端代码
- 客户端创建责任链的各个处理者,并将它们按顺序连接。
- 最后,将请求发送到链中的第一个处理者。
int main() {
auto authHandler = std::make_shared<AuthHandler>();
auto permissionHandler = std::make_shared<PermissionHandler>();
auto businessHandler = std::make_shared<BusinessHandler>();
authHandler->setNext(permissionHandler);
permissionHandler->setNext(businessHandler);
authHandler->handleRequest("auth");
}
优缺点
优点
- 请求处理灵活:
- 可以根据需要动态地改变责任链的结构。
- 解耦请求发送者与处理者:
- 请求发送者不需要知道具体的处理者。
- 职责分离:
- 每个处理者只关注自己的职责。
缺点
- 请求可能未被处理:
- 如果责任链中没有处理者能处理请求,请求可能会被丢弃。
- 调试难度增加:
- 链的结构动态变化,可能导致调试困难。
适用场景
- 多个对象可以处理同一个请求:
- 如任务的审批流程。
- 需要动态组合请求处理逻辑:
- 可以灵活调整处理者的顺序。
- 解耦请求的发送者与接收者:
- 请求发送者不需要直接调用处理者。
总结
职责链模式通过将请求沿着处理者链传递,实现了请求的动态处理。它特别适用于需要动态组合请求处理逻辑,或者需要解耦请求发送者和接收者的场景。