商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C++ 实现轻量级责任链模式 _ 接口抽象与对象链式调用【源码】

C++ 实现轻量级责任链模式 _ 接口抽象与对象链式调用【源码】

  发布于2026-07-03 阅读(0)

扫一扫,手机访问

责任链模式通过抽象处理器接口解耦请求发送者与接收者,定义 `handle()` 和 `setNext()` 纯虚函数,并提供 `passToNext()` 默认实现;`BaseHandler` 基类封装 `next_` 指针与链式跳转逻辑;具体子类专注自身业务逻辑;链由客户端显式构建;上下文采用轻量值语义设计。

C++ 实现轻量级责任链模式 _ 接口抽象与对象链式调用【源码】

责任链模式的核心思路,就是把请求的发送方和接收方彻底解耦。怎么解耦?通过一个统一的处理器接口,让每个具体的处理节点都能被替换、被扩展,而且不会影响到链上的其他环节。那这个接口到底该怎么设计?下面一步步拆开来看。

一、定义抽象处理器接口

抽象处理器接口是整个模式的基石。它需要声明两个关键方法:一个是真正的处理逻辑 `handle()`,另一个是用来构建链条的 `setNext()`。具体来说:

1. 声明纯虚函数 `handle()`,它接收一个通用参数——可以用 `std::any`,也可以直接用一个自定义的上下文类——返回值是 `bool`,表示是否已经处理完毕。如果返回 `true`,链条就停在这里;否则继续往下传。

2. 声明纯虚函数 `setNext()`,参数是一个指向同一接口类型的智能指针(比如 `std::shared_ptr`),负责把下一个节点挂上去。

3. 在接口中顺手提供一个默认实现的辅助方法 `passToNext()`:如果当前节点的 `next_` 不为空,并且当前节点决定不处理(或者处理不了),就直接调用 `next_->handle()` 把请求交给下一个节点。这样一来,子类只需要调用这个方法,就能无缝跳转。

二、实现基础处理器基类

如果每个具体节点都要重复写 `setNext` 和 `passToNext` 的逻辑,那代码就太啰嗦了。所以弄一个模板基类 `BaseHandler`,继承自抽象接口,把公共部分封装好。

1. 构造函数里把 `next_` 初始化为 `nullptr`,确保链的末端是干净的。

2. `setNext()` 的实现很简单:`next_ = next`,直接把传入的指针存起来。

3. `passToNext()` 则检查 `next_` 是否存在:如果有,就返回 `next_->handle(context)`;如果没有,直接返回 `false`,表示链条走到头了也没人能处理。

4. 注意:`handle()` 依然作为纯虚函数保留,强制每个子类去实现自己的业务逻辑——基类只管链条的跳转,不管具体做什么。

三、编写具体处理器子类

每个具体的处理器子类,就是责任链上的一颗螺丝钉。它只关心自己能否处理当前请求,处理完就结束,处理不了就往后传。典型的例子:`AuthHandler` 检查用户权限,`LogHandler` 记录日志,`ValidationHandler` 校验数据格式。

1. 继承 `BaseHandler`,模板参数 `T` 是上下文类型。比如定义一个结构体 `RequestContext { std::string user; int level; }`。

2. 重写 `handle()`:先判断当前节点是否满足处理条件。如果满足,就执行业务逻辑,返回 `true`;如果不满足,直接调用 `passToNext(context)` 把结果返回——注意,这里不要自己手动调用 `next_->handle()`,统一走基类的 `passToNext`,才能保证链式行为的一致性。

3. 每个子类只关注自己那摊事,完全不需要知道链条上还有谁、后面是谁。这才是责任链真正的魅力所在。

四、构建运行时处理器链

链条的组装由客户端负责,这样就能做到按需动态调整:想插一个节点?想换顺序?想移除某个节点?都行,不改代码就能搞定。推荐用工厂函数或者配置文件来驱动链条的初始化。

1. 按执行顺序创建各个处理器实例:auto auth = std::make_shared(); auto log = std::make_shared(); auto validation = std::make_shared();

2. 用 `setNext` 串起来:auth->setNext(log); log->setNext(validation); validation->setNext(nullptr);

3. 最后,把链首节点(比如 `auth`)作为入口句柄保存下来,后续所有请求都从这个入口发起 `handle()` 调用——链条会自己有序地跑完整个流程。

五、设计轻量级上下文对象

上下文是请求信息在链条中传递的载体。如果上下文设计得太重(比如塞一堆智能指针、动态分配内存),性能就会打折扣。更好的做法是采用值语义的小对象:成员尽量是 POD 类型,或者轻量引用(如 `std::string_view`、`const char*`),避免虚函数和动态内存分配。

1. 定义一个结构体 `RequestContext`,只包含 `request_id`、`user_role`、`payload_size` 这类只读字段,值语义传递,拷贝开销极低。

2. 不要在上下文里存 `std::shared_ptr` 或 `std::unique_ptr` 这类管理资源的对象——它们会导致引用计数、生命周期管理等问题,破坏轻量的初衷。

3. 如果后续需要扩展字段,用 `std::optional` 包裹可选成员,这样既能按需携带额外信息,又不会因为默认构造而触发不必要的初始化开销。

本文转载于:https://www.php.cn/faq/2458116.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注