1. 职责链模式基础概念解析
在C++设计模式中,职责链(Chain of Responsibility)是一种行为型模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它为止。这种模式的核心思想是解耦发送者和接收者,让多个对象都有机会处理请求。
1.1 经典实现方式
传统的职责链模式通常通过以下方式实现:
cpp复制class Handler {
public:
virtual ~Handler() = default;
void setNext(Handler* next) { next_ = next; }
virtual void handleRequest(const Request& req) {
if (canHandle(req)) {
processRequest(req);
} else if (next_) {
next_->handleRequest(req);
}
}
protected:
virtual bool canHandle(const Request& req) const = 0;
virtual void processRequest(const Request& req) = 0;
private:
Handler* next_ = nullptr;
};
这种实现有几个明显特点:
- 处理者持有下一个处理者的指针
- 通过虚函数实现多态处理
- 请求会沿着链条传递直到被处理或到达末端
1.2 模式的应用场景
职责链模式特别适合以下场景:
- 有多个对象可以处理同一请求,但具体由哪个对象处理在运行时动态决定
- 需要在不明确接收者的情况下向多个对象中的一个提交请求
- 可动态指定一组对象处理请求
在C++开发中,常见应用包括:
- 事件处理系统(如GUI中的事件冒泡)
- 异常处理机制
- 日志记录器链
- 中间件管道
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. C++中的职责链变体实现
2.1 基于智能指针的自动内存管理
现代C++推荐使用智能指针管理资源,我们可以改造传统实现:
cpp复制class Handler {
public:
using HandlerPtr = std::shared_ptr<Handler>;
void setNext(HandlerPtr next) { next_ = std::move(next); }
void handleRequest(const Request& req) {
if (canHandle(req)) {
processRequest(req);
} else if (next_) {
next_->handleRequest(req);
}
}
protected:
virtual bool canHandle(const Request& req) const = 0;
virtual void processRequest(const Request& req) = 0;
private:
HandlerPtr next_;
};
这种变体的优势:
- 自动内存管理,避免内存泄漏
- 更安全的对象生命周期控制
- 符合现代C++最佳实践
2.2 模板化职责链
利用C++模板可以实现更灵活的职责链:
cpp复制template <typename RequestType>
class Handler {
public:
virtual ~Handler() = default;
void setNext(std::unique_ptr<Handler> next) {
next_ = std::move(next);
}
void handle(const RequestType& req) {
if (canHandle(req)) {
process(req);
} else if (next_) {
next_->handle(req);
}
}
protected:
virtual bool canHandle(const RequestType& req) const = 0;
virtual void process(const RequestType& req) = 0;
private:
std::unique_ptr<Handler> next_;
};
模板化实现的优点:
- 类型安全的请求处理
- 可针对不同请求类型特化处理逻辑
- 编译时多态提高运行时效率
2.3 基于函数对象的轻量级实现
对于简单场景,可以使用std::function实现轻量级职责链:
cpp复制using HandlerFunc = std::function<bool(const Request&)>;
class LightweightChain {
public:
void addHandler(HandlerFunc handler) {
handlers_.push_back(handler);
}
bool handle(const Request& req) {
for (const auto& handler : handlers_) {
if (handler(req)) {
return true;
}
}
return false;
}
private:
std::vector<HandlerFunc> handlers_;
};
这种实现的适用场景:
- 处理逻辑简单,不需要完整类层次
- 需要动态增减处理者
- 性能敏感场景
3. 高级变体与优化技巧
3.1 中断式职责链
有时我们需要在特定条件下中断链条传递:
cpp复制class InterruptibleHandler : public Handler {
public:
enum class Result {
Handled,
NotHandled,
StopPropagation
};
void handleRequest(const Request& req) override {
switch (tryHandle(req)) {
case Result::Handled:
return;
case Result::NotHandled:
if (next_) next_->handleRequest(req);
return;
case Result::StopPropagation:
return;
}
}
protected:
virtual Result tryHandle(const Request& req) = 0;
};
中断机制的应用场景:
- 权限校验失败时终止处理
- 遇到严重错误需要停止后续处理
- 缓存命中时直接返回结果
3.2 并行处理职责链
对于可并行处理的请求,可以实现多线程版本:
cpp复制class ParallelHandler {
public:
void addHandler(std::unique_ptr<Handler> handler) {
handlers_.push_back(std::move(handler));
}
void handle(const Request& req) {
std::vector<std::future<void>> futures;
for (const auto& handler : handlers_) {
futures.push_back(std::async(std::launch::async, [&] {
if (handler->canHandle(req)) {
handler->process(req);
}
}));
}
for (auto& future : futures) {
future.get();
}
}
private:
std::vector<std::unique_ptr<Handler>> handlers_;
};
并行处理的注意事项:
- 确保处理逻辑是线程安全的
- 考虑线程创建开销与任务粒度的平衡
- 需要处理异常传播问题
3.3 带优先级的职责链
通过引入优先级机制可以控制处理顺序:
cpp复制class PrioritizedHandler : public Handler {
public:
struct PriorityHandler {
int priority;
std::unique_ptr<Handler> handler;
bool operator<(const PriorityHandler& other) const {
return priority < other.priority;
}
};
void addHandler(int priority, std::unique_ptr<Handler> handler) {
handlers_.insert({priority, std::move(handler)});
rebuildChain();
}
void handleRequest(const Request& req) override {
if (!chainHead_) return;
chainHead_->handleRequest(req);
}
private:
std::set<PriorityHandler> handlers_;
std::unique_ptr<Handler> chainHead_;
void rebuildChain() {
std::unique_ptr<Handler> current;
for (auto it = handlers_.rbegin(); it != handlers_.rend(); ++it) {
auto newHandler = std::move(it->handler);
newHandler->setNext(std::move(current));
current = std::move(newHandler);
}
chainHead_ = std::move(current);
}
};
优先级机制的典型应用:
- 中间件管道中的优先级处理
- 异常处理中的特定catch块排序
- 日志过滤器的优先级过滤
4. 实际应用案例分析
4.1 游戏引擎中的输入处理
游戏引擎通常使用职责链处理输入事件:
cpp复制class InputHandler {
public:
virtual ~InputHandler() = default;
bool handle(const InputEvent& event) {
if (canHandle(event)) {
process(event);
return true;
}
return next_ ? next_->handle(event) : false;
}
void setNext(std::unique_ptr<InputHandler> next) {
next_ = std::move(next);
}
protected:
virtual bool canHandle(const InputEvent& event) const = 0;
virtual void process(const InputEvent& event) = 0;
private:
std::unique_ptr<InputHandler> next_;
};
// 具体实现示例
class UIInputHandler : public InputHandler {
protected:
bool canHandle(const InputEvent& event) const override {
return event.type == EventType::MouseClick &&
isPointInUI(event.position);
}
void process(const InputEvent& event) override {
// 处理UI点击逻辑
}
};
class GameplayInputHandler : public InputHandler {
protected:
bool canHandle(const InputEvent& event) const override {
return event.type == EventType::KeyPress;
}
void process(const InputEvent& event) override {
// 处理游戏按键逻辑
}
};
4.2 网络中间件管道
网络框架中的中间件常采用职责链模式:
cpp复制class Middleware {
public:
using NextFunc = std::function<void(const Request&, Response&)>;
virtual void execute(const Request& req, Response& res, NextFunc next) = 0;
};
class MiddlewarePipeline {
public:
void add(std::shared_ptr<Middleware> middleware) {
middlewares_.push_back(middleware);
}
void execute(const Request& req, Response& res) {
executeNext(0, req, res);
}
private:
std::vector<std::shared_ptr<Middleware>> middlewares_;
void executeNext(size_t index, const Request& req, Response& res) {
if (index >= middlewares_.size()) return;
auto& middleware = middlewares_[index];
middleware->execute(req, res, [this, index, &res](const Request& req) {
executeNext(index + 1, req, res);
});
}
};
4.3 日志记录器链
日志系统可以使用职责链实现多级日志记录:
cpp复制class LogSink {
public:
virtual ~LogSink() = default;
void setNext(std::unique_ptr<LogSink> next) {
next_ = std::move(next);
}
void log(const LogEntry& entry) {
if (shouldLog(entry)) {
writeLog(entry);
}
if (next_) {
next_->log(entry);
}
}
protected:
virtual bool shouldLog(const LogEntry& entry) const = 0;
virtual void writeLog(const LogEntry& entry) = 0;
private:
std::unique_ptr<LogSink> next_;
};
// 具体实现示例
class ConsoleLogSink : public LogSink {
protected:
bool shouldLog(const LogEntry& entry) const override {
return entry.level >= LogLevel::Info;
}
void writeLog(const LogEntry& entry) override {
std::cout << entry.message << std::endl;
}
};
class FileLogSink : public LogSink {
protected:
bool shouldLog(const LogEntry& entry) const override {
return true; // 记录所有日志
}
void writeLog(const LogEntry& entry) override {
// 写入文件逻辑
}
};
5. 性能优化与最佳实践
5.1 内存布局优化
对于性能敏感的场景,可以考虑连续内存存储:
cpp复制class CompactHandlerChain {
public:
template <typename HandlerType, typename... Args>
void emplace(Args&&... args) {
handlers_.emplace_back(
std::make_unique<HandlerModel<HandlerType>>(
std::forward<Args>(args)...));
}
void handle(const Request& req) {
for (auto& handler : handlers_) {
if (handler->canHandle(req)) {
handler->process(req);
break;
}
}
}
private:
struct HandlerConcept {
virtual ~HandlerConcept() = default;
virtual bool canHandle(const Request&) const = 0;
virtual void process(const Request&) = 0;
};
template <typename T>
struct HandlerModel : HandlerConcept {
template <typename... Args>
HandlerModel(Args&&... args) : handler(std::forward<Args>(args)...) {}
bool canHandle(const Request& req) const override {
return handler.canHandle(req);
}
void process(const Request& req) override {
handler.process(req);
}
T handler;
};
std::vector<std::unique_ptr<HandlerConcept>> handlers_;
};
5.2 缓存热点处理者
通过记录上次成功的处理者优化性能:
cpp复制class CachedHandlerChain : public Handler {
public:
void handleRequest(const Request& req) override {
if (lastHandler_ && lastHandler_->canHandle(req)) {
lastHandler_->processRequest(req);
return;
}
Handler* current = this;
while (current) {
if (current->canHandle(req)) {
lastHandler_ = current;
current->processRequest(req);
return;
}
current = current->next_;
}
}
private:
Handler* lastHandler_ = nullptr;
};
5.3 异步处理模式
对于耗时操作,可以实现异步处理链:
cpp复制class AsyncHandler : public Handler {
public:
void handleRequest(const Request& req) override {
if (canHandle(req)) {
std::async(std::launch::async, [this, req] {
processRequest(req);
});
} else if (next_) {
next_->handleRequest(req);
}
}
};
6. 常见问题与解决方案
6.1 循环引用问题
在使用智能指针时可能出现循环引用:
cpp复制// 错误示例:会导致内存泄漏
class BadHandler {
std::shared_ptr<BadHandler> next_; // 循环引用
public:
void setNext(std::shared_ptr<BadHandler> next) {
next_ = next;
}
};
// 正确做法:使用weak_ptr打破循环
class SafeHandler {
std::weak_ptr<SafeHandler> next_;
public:
void setNext(std::shared_ptr<SafeHandler> next) {
next_ = next;
}
void handle(const Request& req) {
if (canHandle(req)) {
process(req);
} else if (auto next = next_.lock()) {
next->handle(req);
}
}
};
6.2 异常安全处理
确保异常不会破坏职责链完整性:
cpp复制class ExceptionSafeHandler : public Handler {
public:
void handleRequest(const Request& req) noexcept override {
try {
if (canHandle(req)) {
processRequest(req);
} else if (next_) {
next_->handleRequest(req);
}
} catch (...) {
// 记录日志或执行恢复操作
// 但不抛出异常,保持链完整
}
}
};
6.3 动态配置处理链
运行时动态修改处理链的注意事项:
cpp复制class DynamicHandlerChain {
public:
void append(std::unique_ptr<Handler> handler) {
std::lock_guard<std::mutex> lock(mutex_);
if (tail_) {
tail_->setNext(std::move(handler));
tail_ = tail_->next();
} else {
head_ = std::move(handler);
tail_ = head_.get();
}
}
void handle(const Request& req) {
std::lock_guard<std::mutex> lock(mutex_);
if (head_) {
head_->handleRequest(req);
}
}
private:
std::mutex mutex_;
std::unique_ptr<Handler> head_;
Handler* tail_ = nullptr;
};
在实际项目中,我发现职责链模式最容易被滥用的地方是过度设计简单场景。对于只有2-3个处理步骤的情况,直接使用条件语句可能更清晰。职责链真正的价值在于处理那些处理者数量不确定、需要动态配置的场景。
