C++实现设计模式---职责链模式 (Chain of Responsibility)

news2025/1/27 6:30:06

职责链模式 (Chain of Responsibility)

职责链模式 是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。这些对象通过形成一条链,沿着这条链传递请求,直到有对象处理它为止。


意图

  • 通过将请求的发送者与接收者解耦,动态地决定由哪个对象来处理请求。
  • 使多个对象有机会处理请求,而不是由固定的对象处理。

使用场景

  1. 请求的处理者不确定
    • 在运行时,可能需要多个对象来处理请求,但具体的处理者在编译时无法确定。
  2. 需要动态组合请求处理的责任链
    • 希望将多个处理者按顺序动态排列。
  3. 减少耦合
    • 将请求的发送者和处理者解耦。

参与者角色

  1. 处理者接口 (Handler)
    • 定义处理请求的方法,并保存对下一个处理者的引用。
  2. 具体处理者 (ConcreteHandler)
    • 实现处理者接口,处理请求或将请求传递给下一个处理者。
  3. 客户端 (Client)
    • 创建责任链,并向责任链中的第一个处理者发送请求。

示例代码

以下代码展示了职责链模式的实现,用于模拟用户请求的权限校验。系统中有三种责任:身份验证、权限验证和业务处理。

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

// 处理者接口
class Handler {
protected:
    std::shared_ptr<Handler> nextHandler; // 下一个处理者

public:
    virtual ~Handler() = default;

    // 设置下一个处理者
    void setNext(std::shared_ptr<Handler> next) {
        nextHandler = std::move(next);
    }

    // 处理请求的接口
    virtual void handleRequest(const std::string& request) {
        if (nextHandler) {
            nextHandler->handleRequest(request); // 将请求传递给下一个处理者
        }
    }
};

// 具体处理者:身份验证
class AuthHandler : public Handler {
public:
    void handleRequest(const std::string& request) override {
        if (request == "auth") {
            std::cout << "身份验证通过。
";
            if (nextHandler) {
                nextHandler->handleRequest(request); // 传递给下一个处理者
            }
        } else {
            std::cout << "身份验证失败。
";
        }
    }
};

// 具体处理者:权限验证
class PermissionHandler : public Handler {
public:
    void handleRequest(const std::string& request) override {
        if (request == "auth") {
            std::cout << "权限验证通过。
";
            if (nextHandler) {
                nextHandler->handleRequest(request); // 传递给下一个处理者
            }
        } else {
            std::cout << "权限验证失败。
";
        }
    }
};

// 具体处理者:业务处理
class BusinessHandler : public Handler {
public:
    void handleRequest(const std::string& request) override {
        if (request == "auth") {
            std::cout << "业务处理完成。
";
        } else {
            std::cout << "无法进行业务处理。
";
        }
    }
};

// 客户端代码
int main() {
    // 创建处理者
    auto authHandler = std::make_shared<AuthHandler>();
    auto permissionHandler = std::make_shared<PermissionHandler>();
    auto businessHandler = std::make_shared<BusinessHandler>();

    // 构建责任链
    authHandler->setNext(permissionHandler);
    permissionHandler->setNext(businessHandler);

    // 发送请求
    std::cout << "发送请求:auth
";
    authHandler->handleRequest("auth");

    std::cout << "
发送请求:invalid
";
    authHandler->handleRequest("invalid");

    return 0;
}

代码解析

1. 处理者接口 (Handler)
  • 定义了处理请求的接口 handleRequest,并包含对下一个处理者的引用。
  • 通过 setNext 方法设置链中的下一个处理者。
class Handler {
protected:
    std::shared_ptr<Handler> nextHandler; // 下一个处理者
public:
    virtual ~Handler() = default;
    void setNext(std::shared_ptr<Handler> next) {
        nextHandler = std::move(next);
    }
    virtual void handleRequest(const std::string& request) {
        if (nextHandler) {
            nextHandler->handleRequest(request); // 将请求传递给下一个处理者
        }
    }
};
2. 具体处理者 (AuthHandler, PermissionHandler, BusinessHandler)
  • AuthHandler
    • 验证请求是否通过身份认证。
  • PermissionHandler
    • 验证请求是否有权限。
  • BusinessHandler
    • 完成实际的业务逻辑处理。
class AuthHandler : public Handler {
public:
    void handleRequest(const std::string& request) override {
        if (request == "auth") {
            std::cout << "身份验证通过。
";
            if (nextHandler) {
                nextHandler->handleRequest(request);
            }
        } else {
            std::cout << "身份验证失败。
";
        }
    }
};
3. 客户端代码
  • 客户端创建责任链的各个处理者,并将它们按顺序连接。
  • 最后,将请求发送到链中的第一个处理者。
int main() {
    auto authHandler = std::make_shared<AuthHandler>();
    auto permissionHandler = std::make_shared<PermissionHandler>();
    auto businessHandler = std::make_shared<BusinessHandler>();

    authHandler->setNext(permissionHandler);
    permissionHandler->setNext(businessHandler);

    authHandler->handleRequest("auth");
}

优缺点

优点
  1. 请求处理灵活
    • 可以根据需要动态地改变责任链的结构。
  2. 解耦请求发送者与处理者
    • 请求发送者不需要知道具体的处理者。
  3. 职责分离
    • 每个处理者只关注自己的职责。
缺点
  1. 请求可能未被处理
    • 如果责任链中没有处理者能处理请求,请求可能会被丢弃。
  2. 调试难度增加
    • 链的结构动态变化,可能导致调试困难。

适用场景

  1. 多个对象可以处理同一个请求
    • 如任务的审批流程。
  2. 需要动态组合请求处理逻辑
    • 可以灵活调整处理者的顺序。
  3. 解耦请求的发送者与接收者
    • 请求发送者不需要直接调用处理者。

总结

职责链模式通过将请求沿着处理者链传递,实现了请求的动态处理。它特别适用于需要动态组合请求处理逻辑,或者需要解耦请求发送者和接收者的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2283273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在宝塔安装部署mindoc

MinDoc简介 MinDoc 是一款针对IT团队开发的简单好用的文档管理系统。 MinDoc 的前身是 SmartWiki 文档系统。SmartWiki 是基于 PHP 框架 laravel 开发的一款文档管理系统。因 PHP 的部署对普通用户来说太复杂&#xff0c;所以改用 Golang 开发。可以方便用户部署和实用。 开…

蓝桥杯练习日常|递归-进制转换

蓝桥云课760数的计算 一、递归 题目&#xff1a; 我的解题代码&#xff1a; #include <iostream> using namespace std; int sum0; int main() {// 请在此输入您的代码int n;cin>>n;int fun(int n);fun(n); cout<<sum<<\n;return 0; } // void fu…

什么是CIDR技术? 它是如何解决路由缩放问题的

什么是CIDR技术&#xff1f; 它是如何解决路由缩放问题的 一. 什么是 CIDR&#xff1f;二. CIDR 是如何工作的&#xff1f;1. 高效地址分配2. 路由聚合&#xff08;Route Aggregation&#xff09;3. 精确满足需求 三. CIDR 的计算详解1. 子网掩码计算2. 地址范围计算3. 可用 IP…

单片机内存管理剖析

一、概述 在单片机系统中&#xff0c;内存资源通常是有限的&#xff0c;因此高效的内存管理至关重要。合理地分配和使用内存可以提高系统的性能和稳定性&#xff0c;避免内存泄漏和碎片化问题。单片机的内存主要包括程序存储器&#xff08;如 Flash&#xff09;和数据存储器&a…

Qt简单迷宫游戏

目录 你将学到你将准备你将改变你将设计你将编程开始界面游玩界面胜利界面其它bug修复 你可扩展下一篇博客要说的东西 你将学到 Qt中QKeySequence对象的基本创建Qt中QShortcut对象的基本应用Qt中QSoundEffect对象的基本应用 你将准备 在开始制作Qt简单迷宫游戏之前&#xff…

Ansys Thermal Desktop 概述

介绍 Thermal Desktop 是一种用于热分析和流体分析的通用工具。它可用于组件或系统级分析。 来源&#xff1a;CRTech 历史 Thermal Desktop 由 C&R Technologies (CR Tech) 开发。它采用了 SINDA/FLUINT 求解器。SINDA/FLUINT 最初由 CR Tech 的创始人为 NASA 的约翰逊航…

WPF基础 | WPF 基础概念全解析:布局、控件与事件

WPF基础 | WPF 基础概念全解析&#xff1a;布局、控件与事件 一、前言二、WPF 布局系统2.1 布局的重要性与基本原理2.2 常见布局面板2.3 布局的测量与排列过程 三、WPF 控件3.1 控件概述与分类3.2 常见控件的属性、方法与事件3.3 自定义控件 四、WPF 事件4.1 路由事件概述4.2 事…

西门子【Library of General Functions (LGF) for SIMATIC S7-1200 / S7-1500】

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 通用函数库 (LGF) 扩展了 TIA Portal 中用于 PLC 编程的 STEP 7 指令&#xff08;数学函数、时间、计数器 等&#xff09;。该库可以不受限制地使用&#xff0c;并包含 FIFO 、搜索功能、矩阵计算、 astro 计…

Android实战经验篇-AndroidScrcpyClient投屏一

系列文章转如下链接&#xff1a; Android Display Graphics系列文章-汇总 Android实战经验篇-系列文章汇总 本文主要包括部分&#xff1a; 一、方案说明 1.1 适用场景 1.2 方案框架 二、功能演示 2.1 环境准备 2.2 演示 一、方案说明 1.1 适用场景 优秀的开源的scrc…

从 Spark 到 StarRocks:实现58同城湖仓一体架构的高效转型

作者&#xff1a;王世发&#xff0c;吴艳兴等&#xff0c;58同城数据架构部 导读&#xff1a; 本文介绍了58同城在其数据探查平台中引入StarRocks的实践&#xff0c;旨在提升实时查询性能。在面对传统Spark和Hive架构的性能瓶颈时&#xff0c;58同城选择StarRocks作为加速引擎&…

wangEditor富文本编辑器,Laravel上传图片配置和使用

文章目录 前言步骤1. 构造好前端模版2. 搭建后端存储3. 调试 前言 由于最近写项目需要使用富文本编辑器&#xff0c;使用的是VUE3.0版本所以很多不兼容&#xff0c;实际测试以后推荐使用wangEditor 步骤 构造好前端模版搭建后端存储调试 1. 构造好前端模版 安装模版 模版安…

【MySQL】我在广州学Mysql 系列——MySQL用户管理详解

ℹ️大家好&#xff0c;我是练小杰&#xff0c;本博客是春节前最后一篇了&#xff0c;在此感谢大佬们今年的支持&#xff01;&#xff01;&#x1f64f;&#x1f64f; 接下来将学习MYSQL用户管理的相关概念以及命令~~ 回顾&#xff1a;&#x1f449;【MYSQL触发器的使用】 数据…

2025年数学建模美赛 A题分析(3)楼梯使用方向偏好模型

2025年数学建模美赛 A题分析&#xff08;1&#xff09;Testing Time: The Constant Wear On Stairs 2025年数学建模美赛 A题分析&#xff08;2&#xff09;楼梯磨损分析模型 2025年数学建模美赛 A题分析&#xff08;3&#xff09;楼梯使用方向偏好模型 2025年数学建模美赛 A题分…

Spring Security(maven项目) 3.0.2.7版本

通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往复以至无穷&#xf…

【二叉树】4. 判断一颗二叉树是否是平衡二叉树。5. 对称二叉树。6. 二叉树的构建及遍历 7. 二叉树的分层遍历 。

判断一颗二叉树是否是平衡二叉树。OJ链接 可以在求树高度的过程中判断树是否平衡 对称二叉树。OJ链接 二叉树的构建及遍历。OJ链接 注意&#xff1a;public static int i最好把static去掉 否则当有多个测试用例时 i无法重新为0二叉树的分层遍历 。OJ链接 但此题要求返回List…

Java如何实现反转义

Java如何实现反转义 前提 最近做的一个需求&#xff0c;是热搜词增加换一批的功能。功能做完自测后&#xff0c;交给了测试伙伴&#xff0c;但是测试第二天后就提了一个bug&#xff0c;出现了未知词 levis。第一眼看着像公司售卖的一个品牌-李维斯。然后再扒前人写的代码&…

“大模型横扫千军”背后的大数据挖掘--浅谈MapReduce

文章目录 O 背景知识1 数据挖掘2 邦费罗尼原则3 TF.IDF4 哈希函数5 分布式文件系统 一、MapReduce基本介绍1. Map 任务2. 按键分组3. Reduce 任务4. 节点失效处理5.小测验&#xff1a;在一个大型语料库上有100个map任务和若干reduce任务&#xff1a; 二、基于MapReduce的基本运…

蓝桥杯3519 填充 | 分类讨论

题目传送门 很简单&#xff0c;遍历一次字符串&#xff0c;将‘?’作为0或1处理&#xff0c;发现00和11统计次数即可。 s str(input()) cnt 0 arr [00, 11, 0?, ?0, 1?, ?1, ??] i0 while i < len(s)-1:if s[i:(i2)] in arr:i 2cnt 1else:i 1 print(cnt)END✨

嵌入式知识点总结 ARM体系与架构 专题提升(一)-硬件基础

嵌入式知识点总结 ARM体系与架构 专题提升(一)-硬件基础 目录 1.NAND FLASH 和NOR FLASH异同 ? 2.CPU,MPU,MCU,SOC,SOPC联系与差别? 3.什么是交叉编译&#xff1f; 4.为什么要交叉编译&#xff1f; 5.描述一下嵌入式基于ROM的运行方式和基于RAM的运行方式有什么区别? 1…

EchoMimicV2的部署使用

最近有一个录课的需要&#xff0c;我不想浪费人力&#xff0c;只想用技术解决。需求很简单&#xff0c;就是用别人现成的录课视频中的形象和声线&#xff0c;再结合我提供的讲稿去生成一个新的录课视频。我觉得应该有现成的技术了&#xff0c;我想要免费大批量生产。最近看到这…