讲师中心 微信公众号
AI工具推荐 视频效率加速

C++责任链模式如何实现 动态链构建与中断机制

冬明吖_1451

冬明吖_1451

发布时间:2025-08-06 13:23:01

|

689人浏览过

|

来源于php中文网

原创

c++责任链模式通过动态构建处理链并允许在链中中断,实现请求的灵活处理。核心步骤包括:1. 定义抽象处理类handler,提供处理请求的方法和设置下一个处理者的指针;2. 创建具体处理类concretehandler,各自实现特定请求的处理逻辑,若无法处理则传递给下个处理者;3. 动态构建链,客户端通过setnext方法运行时配置处理链;4. 中断机制,处理者可选择是否继续传递请求。此外,复杂参数可通过请求对象、std::any/std::variant、元组等方式传递,并在多线程环境下通过互斥锁、线程安全数据结构、不可变对象等策略保障线程安全。实际应用场景涵盖日志处理、事件处理、身份验证、输入验证、命令处理、金融交易、网络协议栈、编译器设计、游戏开发及工作流引擎等多个领域。

C++责任链模式如何实现 动态链构建与中断机制

C++责任链模式旨在解耦请求的发送者和接收者,通过动态构建链条并允许在链中中断,实现灵活的处理流程。核心在于定义处理请求的接口和链的构建方式,以及决定何时停止传递请求的机制。

C++责任链模式如何实现 动态链构建与中断机制

解决方案:

C++责任链模式如何实现 动态链构建与中断机制

C++责任链模式的实现主要包括以下几个关键步骤:

立即学习“C++免费学习笔记(深入)”;

  1. 定义抽象处理类(Handler): 这是一个基类或接口,定义了处理请求的方法

    handleRequest
    ,以及一个指向下一个处理者的指针
    nextHandler
    。
    handleRequest
    方法通常包含两部分:首先尝试自己处理请求,如果不能处理,则将请求传递给
    nextHandler
    。

    C++责任链模式如何实现 动态链构建与中断机制
    class Handler {
    public:
        virtual ~Handler() = default;
        virtual void handleRequest(int request) {
            if (nextHandler) {
                nextHandler->handleRequest(request);
            }
        }
    
        void setNext(Handler* handler) {
            nextHandler = handler;
        }
    
    protected:
        Handler* nextHandler = nullptr;
    };
  2. 创建具体处理类(ConcreteHandler): 这些类继承自

    Handler
    ,并实现具体的处理逻辑。每个具体处理类负责处理特定类型的请求。如果请求不属于该类处理的范围,则将其传递给链中的下一个处理者。

    class ConcreteHandler1 : public Handler {
    public:
        void handleRequest(int request) override {
            if (request >= 0 && request < 10) {
                std::cout << "ConcreteHandler1 handled request " << request << std::endl;
            } else {
                Handler::handleRequest(request); // Pass to the next handler
            }
        }
    };
    
    class ConcreteHandler2 : public Handler {
    public:
        void handleRequest(int request) override {
            if (request >= 10 && request < 20) {
                std::cout << "ConcreteHandler2 handled request " << request << std::endl;
            } else {
                Handler::handleRequest(request); // Pass to the next handler
            }
        }
    };
  3. 动态链的构建: 链的构建可以在运行时动态进行,这意味着可以根据需要添加或删除处理者。这通常通过

    setNext
    方法实现,允许客户端代码灵活地配置处理链。

    int main() {
        ConcreteHandler1 handler1;
        ConcreteHandler2 handler2;
    
        handler1.setNext(&handler2); // Build the chain: handler1 -> handler2
    
        handler1.handleRequest(5);   // Handled by ConcreteHandler1
        handler1.handleRequest(15);  // Handled by ConcreteHandler2
        handler1.handleRequest(25);  // Not handled, reaches the end of the chain
    
        return 0;
    }
  4. 中断机制: 中断链的传递可以在任何处理者中发生。如果一个处理者能够完全处理请求,它可以选择不将请求传递给链中的下一个处理者。这可以通过简单地不调用

    Handler::handleRequest(request)
    来实现。另外,也可以在Handler中设置一个标志位,用于指示是否允许继续传递请求。

    class InterruptingHandler : public Handler {
    public:
        InterruptingHandler(bool shouldInterrupt) : interrupt(shouldInterrupt) {}
    
        void handleRequest(int request) override {
            std::cout << "InterruptingHandler received request " << request << std::endl;
            if (interrupt) {
                std::cout << "InterruptingHandler is interrupting the chain." << std::endl;
                return; // Stop the chain
            } else {
                Handler::handleRequest(request);
            }
        }
    
    private:
        bool interrupt;
    };
    int main() {
        ConcreteHandler1 handler1;
        InterruptingHandler interruptingHandler(true); // Interrupts the chain
        ConcreteHandler2 handler2;
    
        handler1.setNext(&interruptingHandler);
        interruptingHandler.setNext(&handler2);  // This will not be reached
    
        handler1.handleRequest(5); // Handled by ConcreteHandler1, then reaches InterruptingHandler
    
        return 0;
    }

C++责任链模式的优势在于其灵活性和可扩展性。它允许在运行时动态地配置处理链,并且可以轻松地添加新的处理者,而无需修改现有代码。然而,它也有一些缺点,例如,请求可能会到达链的末尾而没有被处理,这需要仔细的设计和错误处理。

责任链模式如何处理复杂的请求参数传递?

处理复杂请求参数传递,可以考虑以下几种方式:

  1. 使用请求对象(Request Object): 将所有请求参数封装到一个单独的类中。这个类可以包含各种类型的数据,并且可以根据需要在处理链中进行修改。

    class Request {
    public:
        Request(int id, std::string message) : id(id), message(message) {}
    
        int getId() const { return id; }
        std::string getMessage() const { return message; }
        void setMessage(const std::string& newMessage) { message = newMessage; }
    
    private:
        int id;
        std::string message;
    };
    
    class Handler {
    public:
        virtual ~Handler() = default;
        virtual void handleRequest(Request& request) {
            if (nextHandler) {
                nextHandler->handleRequest(request);
            }
        }
    
        void setNext(Handler* handler) {
            nextHandler = handler;
        }
    
    protected:
        Handler* nextHandler = nullptr;
    };
    
    class ConcreteHandler1 : public Handler {
    public:
        void handleRequest(Request& request) override {
            if (request.getId() >= 0 && request.getId() < 10) {
                std::cout << "ConcreteHandler1 handled request with id " << request.getId() << " and message: " << request.getMessage() << std::endl;
                request.setMessage("Message processed by Handler1");
            } else {
                Handler::handleRequest(request);
            }
        }
    };
  2. 使用

    std::any
    或
    std::variant
    :
    如果请求参数的类型不确定,可以使用
    std::any
    或
    std::variant
    来存储参数。这允许处理链中的每个处理者根据需要提取和处理参数。但是,这需要进行类型检查,以确保处理者能够处理特定类型的参数。

    #include <any>
    #include <iostream>
    
    class Handler {
    public:
        virtual ~Handler() = default;
        virtual void handleRequest(std::any request) {
            if (nextHandler) {
                nextHandler->handleRequest(request);
            }
        }
    
        void setNext(Handler* handler) {
            nextHandler = handler;
        }
    
    protected:
        Handler* nextHandler = nullptr;
    };
    
    class IntHandler : public Handler {
    public:
        void handleRequest(std::any request) override {
            try {
                int value = std::any_cast<int>(request);
                std::cout << "IntHandler handled request: " << value << std::endl;
            } catch (const std::bad_any_cast& e) {
                std::cout << "IntHandler cannot handle this type." << std::endl;
                Handler::handleRequest(request);
            }
        }
    };
  3. 使用元组(Tuple): 将多个参数打包到一个元组中,并将其传递给处理链。每个处理者可以根据需要从元组中提取参数。

  4. 使用消息队列: 对于更复杂的系统,可以使用消息队列来传递请求。每个处理者可以订阅特定类型的消息,并处理接收到的消息。

C++责任链模式在多线程环境下如何保证线程安全?

在多线程环境中使用责任链模式,需要特别注意线程安全问题。以下是一些保证线程安全的策略:

  1. 保护共享资源: 处理链中的共享资源(例如,处理者列表、处理者状态)需要使用互斥锁(

    std::mutex
    )或其他同步机制进行保护。

    C++14
    C++14

    C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

    下载
    #include <mutex>
    #include <vector>
    #include <algorithm>
    
    class ThreadSafeHandler {
    public:
        virtual ~ThreadSafeHandler() = default;
        virtual void handleRequest(int request) {
            std::lock_guard<std::mutex> lock(mutex);
            if (nextHandler) {
                nextHandler->handleRequest(request);
            }
        }
    
        void setNext(ThreadSafeHandler* handler) {
            std::lock_guard<std::mutex> lock(mutex);
            nextHandler = handler;
        }
    
    protected:
        ThreadSafeHandler* nextHandler = nullptr;
        std::mutex mutex;
    };
  2. 使用线程安全的数据结构: 如果处理链需要存储数据,请使用线程安全的数据结构(例如,

    std::atomic
    、线程安全的队列)。

  3. 避免共享可变状态: 尽量避免在处理者之间共享可变状态。如果必须共享状态,请使用原子操作或互斥锁来保护状态的访问。

  4. 使用不可变对象: 如果可能,使用不可变对象来传递请求。这可以避免多个线程同时修改请求对象的问题。

  5. 线程局部存储: 可以使用线程局部存储(

    thread_local
    )来为每个线程创建独立的处理链副本。这可以避免多个线程竞争共享的处理链。

  6. 无锁编程: 在某些情况下,可以使用无锁编程技术来提高性能。但是,无锁编程非常复杂,需要仔细的设计和测试。

  7. 读写锁: 如果读操作远多于写操作,可以考虑使用读写锁(

    std::shared_mutex
    )来提高并发性能。

  8. 原子操作: 使用原子操作(

    std::atomic
    )来保护简单的状态变量,例如计数器或标志位。

C++责任链模式在实际项目中的应用场景有哪些?

C++责任链模式在实际项目中有广泛的应用,特别是在需要灵活处理请求或事件的场景中。

  1. 日志处理: 可以使用责任链模式来处理不同级别的日志消息。每个处理者可以负责处理特定级别的日志消息(例如,调试、信息、警告、错误)。

  2. 事件处理: 在图形用户界面(GUI)框架中,可以使用责任链模式来处理用户事件(例如,鼠标点击、键盘按键)。每个处理者可以负责处理特定类型的事件。

  3. 身份验证和授权: 可以使用责任链模式来实现身份验证和授权流程。每个处理者可以负责执行特定的身份验证或授权步骤。

  4. 输入验证: 可以使用责任链模式来验证用户输入。每个处理者可以负责验证特定类型的输入(例如,电子邮件地址、电话号码)。

  5. 命令处理: 可以使用责任链模式来处理命令。每个处理者可以负责执行特定的命令。

  6. 金融交易处理: 在金融系统中,可以使用责任链模式来处理金融交易。每个处理者可以负责执行特定的交易步骤(例如,风险评估、合规检查)。

  7. 网络协议栈: 在网络协议栈中,可以使用责任链模式来处理网络数据包。每个处理者可以负责处理特定协议层的数据包。

  8. 编译器: 在编译器设计中,责任链模式可以用于处理代码的不同阶段,例如词法分析、语法分析、语义分析和代码生成。每个处理者负责一个特定的编译阶段。

  9. 游戏开发: 在游戏开发中,责任链模式可以用于处理游戏对象的行为。例如,不同的处理者可以负责处理不同的碰撞事件或AI决策。

  10. 工作流引擎: 工作流引擎可以使用责任链模式来定义和执行工作流。每个处理者可以负责执行工作流中的一个步骤。

热门AI工具

更多
Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

相关专题

更多
C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

379

2026.04.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2741

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

376

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

417

2026.01.06

C++ 数据结构与算法实现教程合集
C++ 数据结构与算法实现教程合集

以 C++ 为实现语言,系统讲解核心数据结构与算法,涵盖链表(单链表/双链表/环检测)、栈与队列(单调栈/优先队列)、二叉树(遍历/BST/AVL/红黑树)、哈希表(开地址法/链地址法)、图(邻接表/BFS/DFS/Dijkstra/拓扑排序)、常见排序算法(快排/归并/堆排/计数排序)的实现与复杂度分析,同时分享 LeetCode 刷题技巧、竞赛编程常用模板(二分/前缀和/滑动窗口/动态规划),帮助开发者夯实算法基础。

492

2026.05.09

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3208

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

5209

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3849

2025.12.29

Uvicorn 报错与问题解决教程
Uvicorn 报错与问题解决教程

本专题汇总了Uvicorn服务器常见问题与报错解决的教程合集,涵盖启动失败、端口占用、模块导入错误、事件循环冲突及热重载失效等典型故障的排查思路。同时整理了多进程与Worker配置、SSL/HTTPS证书报错、跨域与代理配置等实战解决方案,助你快速定位并解决Uvicorn运行中的各类问题。

0

2026.11.02

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn