导读:本期聚焦于小伙伴创作的《如何用C++实现轻量级责任链模式并通过接口抽象完成指针链式调用》,敬请观看详情。责任链模式常被认为需要复杂框架支撑,其实在C++里用抽象基类和智能指针就能搭出轻量实现。核心是把每个处理节点抽象成统一接口,节点内部持有指向下一个节点的指针,请求沿链传递直到被处理。相比继承树爆炸的写法,这种链式结构让新增处理逻辑不需改动旧代码。本文给出可编译源码,说明如何用weak_ptr避免循环引用,以及怎样在运行时动态组装处理链。掌握该写法后,日志过滤、权限校验等场景都能直接用同一套骨架,既保持类型安全又降低模块耦合。

责任链模式属于行为型设计模式,目的是让多个对象都有机会处理请求,从而避免请求发送者与接收者之间的强耦合。在C++中,我们可以通过抽象接口定义统一的处理契约,再利用指针将各个处理器串成一条链。每个处理器在收到请求时自行判断能否处理,不能处理就转交给后继节点。这种写法没有第三方库依赖,头文件加上几十行实现就能用在生产环境。

如何用C++实现轻量级责任链模式并通过接口抽象完成指针链式调用

一、接口抽象的设计思路

轻量级实现的第一步是抽出公共接口。我们定义一个名为 Handler 的抽象基类,里面包含一个纯虚函数 handle,以及用于设置下一个节点的 setNext 方法。由于 C++ 没有像 Java 那样的接口关键字,用纯虚类即可表达契约。为了资源管理安全,链中保存的后续节点指针建议使用 shared_ptr,而在节点内部反向引用时可用 weak_ptr 防止循环引用导致内存泄漏。

为什么强调接口抽象而不是具体类互调?假如每个处理逻辑都直接调用下一个具体类,新增一种处理器就要改旧类的代码,违反开闭原则。抽象之后,链条的组装方只依赖 Handler 类型,具体节点可随时替换或增减。下面的代码展示了基础接口与两个具体实现。

#include <iostream>
#include <memory>
#include <string>

class Handler {
public:
    virtual ~Handler() = default;
    virtual bool handle(const std::string& request) = 0;
    void setNext(std::shared_ptr<Handler> next) {
        next_ = next;
    }
    std::shared_ptr<Handler> getNext() const {
        return next_;
    }
private:
    std::shared_ptr<Handler> next_;
};

class AuthHandler : public Handler {
public:
    bool handle(const std::string& request) override {
        if (request == "auth") {
            std::cout << "AuthHandler processed" << std::endl;
            return true;
        }
        if (auto n = getNext()) return n->handle(request);
        return false;
    }
};

class LogHandler : public Handler {
public:
    bool handle(const std::string& request) override {
        std::cout << "LogHandler logged: " << request << std::endl;
        if (auto n = getNext()) return n->handle(request);
        return false;
    }
};

二、指针链式调用的组装方式

有了接口和节点,下一步是把它们连起来。所谓指针链式调用,是指用对象本身的指针返回来实现连续设置,比如 obj.setNext(a).setNext(b) 这样的语法。在 C++ 里只要让 setNext 返回自身引用即可。这样写出来的组装代码读起来像一条流水线,也方便在配置阶段动态拼装不同顺序的处理器。

需要注意的是,如果返回的是裸指针容易发生空指针问题,返回 shared_ptr 的引用又可能延长生命周期。实践中返回 Handler& 或 shared_ptr<Handler> 都可以,前者更轻量。下面例子演示了如何让 setNext 支持链式写法,并给出主函数中的调用示范。

#include <memory>

class ChainHandler : public Handler {
public:
    // 返回自身引用以支持链式调用
    ChainHandler& setNext(std::shared_ptr<Handler> next) {
        Handler::setNext(next);
        return *this;
    }
    bool handle(const std::string& request) override {
        std::cout << "ChainHandler got: " << request << std::endl;
        if (auto n = getNext()) return n->handle(request);
        return false;
    }
};

int main() {
    auto auth = std::make_shared<AuthHandler>();
    auto log = std::make_shared<LogHandler>();
    auto chain = std::make_shared<ChainHandler>();
    // 指针链式调用组装
    chain->setNext(auth).setNext(log);
    chain->handle("auth");
    chain->handle("other");
    return 0;
}

三、避免循环引用与资源释放

当责任链节点互相持有 shared_ptr 时,若某个节点又指回前面的节点,引用计数永远降不到零,会造成内存泄漏。解决办法是链条只单向持有 next 的 shared_ptr,如果业务需要反向通知,用 weak_ptr 观察即可。由于我们的轻量设计是单向传递,正常组装不会成环,但用户在运行时动态重设 next 时要避免把已有前驱节点设为自己的后继。

另一个细节是析构顺序。shared_ptr 管理的 Handler 析构时会自动释放后续节点,无需手动 delete。如果处理器内部含有文件句柄或网络连接,应在析构函数中关闭。下面的表格对比了裸指针与智能指针在责任链中的差异。

方式内存安全组装便利性适用场景
裸指针易泄漏需手动管理极简Demo
shared_ptr自动释放支持链式生产环境
weak_ptr配合防环引用稍复杂双向需求

四、实际应用场景与扩展

轻量责任链特别适合请求需经多道关卡的场景,例如 Web 框架里的鉴权、限流、参数校验。每增加一种检查只需新建 Handler 子类并插入链中,原有逻辑不受影响。如果希望链中途截断,让某个节点处理完不再往下传,只需在 handle 中返回 true 且不调用 getNext 即可。

进一步扩展时,可给 Handler 增加优先级字段,组装前按优先级排序;或者把链本身做成一个容器,用 vector 存储处理器,循环调用。但那就偏离了经典指针链式的结构。保持指针链接的好处是运行时可动态拆装,比如热更新时替换某个节点而不影响整条链。以下代码展示了一个带优先级的简单扩展思路。

#include <vector>
#include <algorithm>

class PriorityHandler : public Handler {
public:
    PriorityHandler(int p) : priority_(p) {}
    int priority() const { return priority_; }
    bool handle(const std::string& request) override {
        std::cout << "Priority " << priority_ << " handled" << std::endl;
        if (auto n = getNext()) return n->handle(request);
        return true;
    }
private:
    int priority_;
};

void buildChain(std::vector<std::shared_ptr<PriorityHandler>>& vec) {
    std::sort(vec.begin(), vec.end(),
        [](auto& a, auto& b){ return a->priority() < b->priority(); });
    for (size_t i = 0; i + 1 < vec.size(); ++i) {
        vec[i]->setNext(vec[i+1]);
    }
}

通过上述方式,我们用极少的代码在 C++ 中落地了责任链模式。接口抽象保证了扩展性,指针链式调用让组装直观,智能指针解决了资源管理痛点。读者可直接将示例源码复制到工程里,根据业务填充 handle 逻辑即可。

C++责任链模式指针链式调用修改时间:2026-08-01 23:18:34

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。