1. 职责链模式基础回顾
职责链模式(Chain of Responsibility)是行为型设计模式中的经典实现,它通过将请求的发送者和接收者解耦,使多个对象都有机会处理请求。在C++中,这种模式特别适合处理需要动态确定处理者的场景。
1.1 核心概念解析
职责链模式的核心在于构建一条处理者链,每个处理者都包含对下一个处理者的引用。当一个请求到来时,它会沿着这条链传递,直到有处理者能够处理它为止。这种设计带来几个显著优势:
- 降低耦合度:请求发送者无需知道具体由哪个对象处理
- 动态配置:可以在运行时动态改变处理链
- 灵活扩展:新增处理者只需修改链配置,不影响现有代码
1.2 典型实现结构
标准的C++职责链实现通常包含以下组件:
cpp复制class Handler {
public:
virtual Handler* setNext(Handler* handler) = 0;
virtual void handleRequest(const std::string& request) = 0;
};
class BaseHandler : public Handler {
protected:
Handler* nextHandler;
public:
BaseHandler() : nextHandler(nullptr) {}
Handler* setNext(Handler* handler) override {
nextHandler = handler;
return handler; // 支持链式调用
}
void handleRequest(const std::string& request) override {
if(nextHandler) {
nextHandler->handleRequest(request);
}
}
};
class ConcreteHandlerA : public BaseHandler {
public:
void handleRequest(const std::string& request) override {
if(canHandle(request)) {
// 处理逻辑
} else {
BaseHandler::handleRequest(request); // 传递给下一个
}
}
private:
bool canHandle(const std::string& req) {
// 判断条件
}
};
2. 高级应用场景分析
2.1 动态优先级调整
在实际项目中,处理者的优先级可能需要动态调整。我们可以通过引入权重机制来实现:
cpp复制class WeightedHandler : public BaseHandler {
int weight;
public:
WeightedHandler(int w) : weight(w) {}
// 重写setNext以支持按权重排序
Handler* setNext(Handler* handler) override {
if(auto wh = dynamic_cast<WeightedHandler*>(handler)) {
if(wh->weight < this->weight) {
wh->nextHandler = this->nextHandler;
this->nextHandler = wh;
return this;
}
}
return BaseHandler::setNext(handler);
}
};
2.2 多条件分支处理
复杂系统可能需要基于多个条件进行路由:
cpp复制class MultiConditionHandler : public BaseHandler {
std::vector<std::function<bool(const std::string&)>> conditions;
public:
void addCondition(std::function<bool(const std::string&)> cond) {
conditions.push_back(cond);
}
void handleRequest(const std::string& request) override {
for(auto& cond : conditions) {
if(cond(request)) {
// 处理逻辑
return;
}
}
BaseHandler::handleRequest(request);
}
};
3. 性能优化技巧
3.1 短路评估优化
对于性能敏感场景,可以在处理链中实现短路逻辑:
cpp复制class FastHandler : public BaseHandler {
public:
void handleRequest(const std::string& request) override {
if(shouldStop(request)) {
return; // 提前终止链
}
// ...处理逻辑
BaseHandler::handleRequest(request);
}
};
3.2 缓存处理结果
对于重复请求,可以引入缓存机制:
cpp复制class CachingHandler : public BaseHandler {
std::unordered_map<std::string, std::string> cache;
public:
void handleRequest(const std::string& request) override {
if(cache.count(request)) {
// 返回缓存结果
return;
}
// ...处理逻辑
cache[request] = result;
BaseHandler::handleRequest(request);
}
};
4. 实际工程实践
4.1 日志处理系统实现
一个完整的日志级别处理示例:
cpp复制class LogHandler : public BaseHandler {
LogLevel level;
public:
LogHandler(LogLevel lvl) : level(lvl) {}
void handleRequest(const LogMessage& msg) override {
if(msg.level >= this->level) {
// 写入日志
if(msg.level >= LogLevel::Error) {
return; // 错误日志不继续传递
}
}
BaseHandler::handleRequest(msg);
}
};
// 使用示例
auto debug = new LogHandler(LogLevel::Debug);
auto info = new LogHandler(LogLevel::Info);
auto error = new LogHandler(LogLevel::Error);
debug->setNext(info)->setNext(error);
4.2 网络请求过滤器
构建HTTP请求过滤链:
cpp复制class HttpFilter : public BaseHandler {
public:
void handleRequest(HttpRequest& req) override {
if(!filter(req)) {
req.setStatusCode(403);
return;
}
BaseHandler::handleRequest(req);
}
protected:
virtual bool filter(const HttpRequest& req) = 0;
};
class AuthFilter : public HttpFilter {
bool filter(const HttpRequest& req) override {
return req.hasHeader("Authorization");
}
};
class RateLimitFilter : public HttpFilter {
bool filter(const HttpRequest& req) override {
// 限流逻辑
}
};
5. 常见问题与解决方案
5.1 循环引用检测
处理链中可能出现循环引用,需要检测:
cpp复制bool hasCycle(Handler* head) {
auto slow = head;
auto fast = head;
while(fast && fast->nextHandler) {
slow = slow->nextHandler;
fast = fast->nextHandler->nextHandler;
if(slow == fast) {
return true;
}
}
return false;
}
5.2 内存管理策略
推荐使用智能指针管理处理者生命周期:
cpp复制using HandlerPtr = std::shared_ptr<Handler>;
class HandlerManager {
std::vector<HandlerPtr> handlers;
HandlerPtr chainHead;
public:
template<typename T, typename... Args>
void addHandler(Args&&... args) {
auto handler = std::make_shared<T>(std::forward<Args>(args)...);
if(handlers.empty()) {
chainHead = handler;
} else {
handlers.back()->setNext(handler.get());
}
handlers.push_back(handler);
}
};
6. 现代C++特性应用
6.1 使用lambda简化处理者
C++11后可以用lambda快速创建处理者:
cpp复制auto handler = make_handler([](const auto& req) {
if(req.contains("special")) {
// 处理逻辑
return true;
}
return false;
});
handler->setNext(defaultHandler);
6.2 可变模板构建链
利用模板元编程构建类型安全的处理链:
cpp复制template<typename... Handlers>
auto make_chain(Handlers&... handlers) {
std::tuple<Handlers&...> chain(handlers...);
// 编译期展开设置next关系
[]<size_t... I>(std::index_sequence<I...>, auto& t) {
((std::get<I>(t).setNext(&std::get<I+1>(t))), ...);
}(std::make_index_sequence<sizeof...(Handlers)-1>{}, chain);
return &std::get<0>(chain);
}
7. 测试与调试技巧
7.1 单元测试策略
为职责链编写测试用例时应注意:
cpp复制TEST(HandlerChainTest, BasicRouting) {
auto handlerA = new ConcreteHandlerA();
auto handlerB = new ConcreteHandlerB();
handlerA->setNext(handlerB);
TestRequest req1("typeA");
handlerA->handleRequest(req1);
EXPECT_TRUE(req1.handledByA());
TestRequest req2("typeB");
handlerA->handleRequest(req2);
EXPECT_TRUE(req2.handledByB());
delete handlerA;
delete handlerB;
}
7.2 调试日志注入
为处理链添加调试支持:
cpp复制class DebugHandler : public BaseHandler {
std::string name;
public:
DebugHandler(std::string n) : name(std::move(n)) {}
void handleRequest(const std::string& request) override {
std::cout << "[" << name << "] processing: " << request << "\n";
BaseHandler::handleRequest(request);
std::cout << "[" << name << "] completed: " << request << "\n";
}
};
8. 性能对比与选型建议
8.1 与策略模式对比
职责链与策略模式的主要区别:
| 特性 | 职责链模式 | 策略模式 |
|---|---|---|
| 处理方式 | 顺序尝试 | 直接选择 |
| 运行时开销 | 可能较高 | 通常较低 |
| 灵活性 | 动态调整链 | 需明确策略 |
| 适用场景 | 处理者未知 | 策略已知 |
8.2 与状态模式对比
与状态模式的关键差异:
- 状态模式:对象行为随内部状态改变
- 职责链:多个对象尝试处理同一请求
- 状态转换 vs 请求传递
9. 设计模式组合应用
9.1 与工厂模式结合
使用工厂创建处理链:
cpp复制class HandlerFactory {
public:
static Handler* createChain(const std::string& config) {
// 解析配置创建链
Handler* head = nullptr;
Handler* current = nullptr;
for(auto& item : parseConfig(config)) {
auto handler = createHandler(item.type);
if(!head) head = handler;
if(current) current->setNext(handler);
current = handler;
}
return head;
}
};
9.2 与观察者模式结合
实现处理完成通知:
cpp复制class ObservableHandler : public BaseHandler {
std::vector<std::function<void()>> observers;
public:
void addObserver(std::function<void()> obs) {
observers.push_back(obs);
}
void handleRequest(const std::string& request) override {
BaseHandler::handleRequest(request);
notifyObservers();
}
private:
void notifyObservers() {
for(auto& obs : observers) {
obs();
}
}
};
10. 实际项目经验分享
在大型金融系统中使用职责链处理交易风控的经验:
- 每个风控规则作为一个处理者
- 规则按优先级排序形成链
- 交易请求通过整个风控链
- 任一规则拒绝则终止流程
- 动态加载新规则不影响现有系统
关键优化点:
- 高频规则前置
- 缓存规则检查结果
- 并行执行独立规则检查
- 规则权重动态调整
