C# 设计模式(行为型模式):责任链模式

news2025/1/7 5:05:54

C# 设计模式(行为型模式):责任链模式

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,用于让多个对象有机会处理同一个请求,避免请求发送者与接收者之间的耦合。它通过将请求沿着一条链传递,直到某个对象处理它,从而实现了请求和处理者的动态解耦。


一、责任链模式的核心概念
  1. 请求传递:将请求从一个对象传递到下一个对象,直到找到能够处理请求的对象为止。
  2. 职责分离:每个对象专注于处理自己的职责,其他职责交由链上的其他对象处理。
  3. 动态链条:链条的结构可以动态调整,灵活扩展。

二、模式结构

在责任链模式中,通常包含以下角色:

  1. Handler(抽象处理者)
    定义一个接口,声明处理请求的方法,以及一个引用指向下一个处理者。

  2. ConcreteHandler(具体处理者)
    实现抽象处理者接口,负责处理具体的请求。如果不能处理,则将请求传递给下一个处理者。

  3. Client(客户端)
    创建并配置责任链,并向链的起点发出请求。


三、适用场景
  • 职责分散:需要将职责分散到多个对象中,以便降低耦合度。
  • 动态处理:某些请求需要灵活地由不同的对象处理。
  • 多级审批:如审批系统、权限管理等需要逐级处理的场景。

四、C# 实现案例
1. 场景描述

假设一个公司有以下审批流程:

  • 如果报销金额小于 1000 元,由经理审批。
  • 如果金额在 1000 元到 5000 元之间,由总监审批。
  • 如果金额超过 5000 元,由副总裁审批。
2. 实现代码
using System;

namespace ChainOfResponsibilityExample
{
    // 抽象处理者
    abstract class Approver
    {
        protected Approver NextApprover;

        public void SetNext(Approver nextApprover)
        {
            NextApprover = nextApprover;
        }

        public abstract void HandleRequest(PurchaseRequest request);
    }

    // 具体处理者:经理
    class Manager : Approver
    {
        public override void HandleRequest(PurchaseRequest request)
        {
            if (request.Amount < 1000)
            {
                Console.WriteLine($"经理批准了金额为 {request.Amount} 元的请求。");
            }
            else if (NextApprover != null)
            {
                NextApprover.HandleRequest(request);
            }
        }
    }

    // 具体处理者:总监
    class Director : Approver
    {
        public override void HandleRequest(PurchaseRequest request)
        {
            if (request.Amount >= 1000 && request.Amount <= 5000)
            {
                Console.WriteLine($"总监批准了金额为 {request.Amount} 元的请求。");
            }
            else if (NextApprover != null)
            {
                NextApprover.HandleRequest(request);
            }
        }
    }

    // 具体处理者:副总裁
    class VicePresident : Approver
    {
        public override void HandleRequest(PurchaseRequest request)
        {
            if (request.Amount > 5000)
            {
                Console.WriteLine($"副总裁批准了金额为 {request.Amount} 元的请求。");
            }
            else if (NextApprover != null)
            {
                NextApprover.HandleRequest(request);
            }
        }
    }

    // 请求类
    class PurchaseRequest
    {
        public double Amount { get; }

        public PurchaseRequest(double amount)
        {
            Amount = amount;
        }
    }

    // 客户端
    class Program
    {
        static void Main(string[] args)
        {
            // 构建责任链
            Approver manager = new Manager();
            Approver director = new Director();
            Approver vicePresident = new VicePresident();

            manager.SetNext(director);
            director.SetNext(vicePresident);

            // 模拟请求
            var request1 = new PurchaseRequest(500);
            var request2 = new PurchaseRequest(3000);
            var request3 = new PurchaseRequest(10000);

            manager.HandleRequest(request1);
            manager.HandleRequest(request2);
            manager.HandleRequest(request3);
        }
    }
}

五、运行结果

执行上述代码后,输出如下:

经理批准了金额为 500 元的请求。
总监批准了金额为 3000 元的请求。
副总裁批准了金额为 10000 元的请求。

六、优缺点分析
优点
  1. 解耦请求与处理者:发送者无需知道具体的处理者是谁,减少了系统耦合。
  2. 职责分离:每个处理者只需专注于自己的职责,代码清晰易维护。
  3. 易于扩展:可以轻松添加新的处理者,调整链条结构。
缺点
  1. 可能无处理者响应:如果链的末端没有处理请求的逻辑,可能导致请求丢失。
  2. 性能开销:请求需要沿着链传递,链条过长可能影响性能。

七、实际应用场景
  1. 审批流程:多级审批系统中,每个级别的管理者负责不同金额范围的审批。
  2. 日志处理:不同级别的日志可以由不同的处理器记录(如控制台、文件或远程服务器)。
  3. 权限验证:多级权限验证链,根据用户角色处理请求。

八、总结

责任链模式是一种优雅的设计模式,适用于需要动态分配职责的场景。通过它,可以实现请求发送者与处理者的解耦,使系统具有更好的扩展性和灵活性。如果你正在设计一个多级处理的系统,不妨试试责任链模式!

希望这篇文章能帮助你更好地理解责任链模式!如果有疑问或建议,欢迎在评论区留言 😊

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

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

相关文章

df.groupby()方法使用表达式分组

# 索引值是否为偶数&#xff0c;分成两组 df.groupby(lambda x:x%20).sum() df.groupby(df.index%20).sum() # 同上这两个写法看似相似&#xff0c;确实都基于索引值来进行分组&#xff0c;但在实现方式上有细微的区别&#xff1a; df.groupby(lambda x: x % 2 0) 这种方式通过…

Python 数据可视化的完整指南

目录 一、为什么选择 Python 进行数据可视化? 二、常用 Python 可视化库及其特点 三、常用图表类型及其代码示例 折线图:用于展示数据随时间或其他连续变量的变化趋势。 柱状图:用于比较不同类别的数据大小。 散点图:用于展示两个变量之间的关系,并发现数据中的模式…

国内Ubuntu环境Docker部署CosyVoice

国内Ubuntu环境Docker部署CosyVoice 本文旨在记录在 国内 CosyVoice项目在 Ubuntu 环境下如何使用 dockermin-conda进行一键部署。 源项目地址&#xff1a; https://github.com/FunAudioLLM/CosyVoice 如果想要使用 dockerpython 进行部署&#xff0c;可以参考我另一篇博客中的…

Git的使用流程(详细教程)

目录 01.Git是什么&#xff1f; 1.1 Git简介 1.2 SVN与Git的最主要的区别 1.3 GIt主要特点 02.Git是干什么的&#xff1f; 2.1.Git概念汇总 2.2 工作区/暂存区/仓库 2.3 Git使用流程 03.Git的安装配置 3.1 Git的配置文件 3.2 配置-初始化用户 3.3 Git可视化…

ImageNet 2.0?自动驾驶数据集迎来自动标注新时代

引言&#xff1a; 3DGS因其渲染速度快和高质量的新视角合成而备受关注。一些研究人员尝试将3DGS应用于驾驶场景的重建。然而&#xff0c;这些方法通常依赖于多种数据类型&#xff0c;如深度图、3D框和移动物体的轨迹。此外&#xff0c;合成图像缺乏标注也限制了其在下游任务中的…

npm install --global windows-build-tools --save 失败

注意以下点 为啥下载windows-build-tools&#xff0c;是因为node-sass4.14.1 一直下载不成功&#xff0c;提示python2 没有安装&#xff0c;最终要安装这个&#xff0c;但是安装这个又失败&#xff0c;主要有以下几个要注意的 1、node 版本 14.21.3 不能太高 2、管理员运行 …

Beamer-LaTeX学习(教程批注版)【1】

该文档总体由beamer-latex的教程而来&#xff0c;由耳东小白以自身学习路径整理。因其中要点基本按照教程的顺序和结构整理&#xff0c;故而不能称之为完全原创&#xff0c;但也不是翻译&#xff0c;更不是抄袭&#xff0c;是个人自学笔记和批注&#xff0c;其中添加了小白个人…

wx005基于springboot+vue+uniapp的大学生心理健康测评管理系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

SpringBoot整合springmvc、扩展springmvc

目录 一、 SpringMVC三大组件二、 Spring MVC 组件的自动管理2.1 中央转发器&#xff08;DispatcherServlet&#xff09;2.2 控制器2.3 视图解析器自动管理2.4 静态资源访问2.5 消息转换和格式化2.6 欢迎页面的自动配置 三、Springboot扩展springmvc3.1 视图控制器注册&#xf…

STM32使用UART发送字符串与printf输出重定向

首先我们先看STM32F103C8T6的电路图 由图可知&#xff0c;其PA9和PA10引脚分别为UART的TX和RX(注意&#xff1a;这个电路图是错误的&#xff0c;应该是PA9是X而PA9是RX&#xff0c;我们看下图的官方文件可以看出)&#xff0c;那么接下来我们应该找到该引脚的定义是什么&#xf…

力扣28找出字符串中第一个匹配项的下标

class Solution:def strStr(self, haystack: str, needle: str) -> int:# 特殊情况处理if not needle:return 0# 获取 haystack 和 needle 的长度a len(needle)b len(haystack)# 遍历 haystack&#xff0c;检查每个子字符串是否与 needle 匹配for i in range(b - a 1):if…

8、RAG论文笔记(Retrieval-Augmented Generation检索增强生成)

RAG论文笔记 1、 **研究背景与动机**2、方法概述3、RAG 模型架构3.1总体架构3.2 Generator&#xff08;生成器&#xff09;3.3 检索器&#xff08;Retriever&#xff09;3.4训练&#xff08;Training&#xff09;3.5**解码方法**&#xff08;求近似 &#xff09;3.6微调的参数 …

PCA降维算法详细推导

关于一个小小的PCA的推导 文章目录 关于一个小小的PCA的推导1 谱分解 (spectral decomposition)2 奇异矩阵(singular matrix)3 酉相似(unitary similarity)4 酉矩阵5 共轭变换6 酉等价7 矩阵的迹的计算以及PCA算法推导8 幂等矩阵(idempotent matrix)9 Von Neumanns 迹不等式 [w…

Android studio 旧版本下载,NDK旧版本下载

记录一下旧版的ndk 和 Android studio 官方下载备份。 1.NDK 旧版本下载地址 下载地址&#xff1a;https://github.com/android/ndk/wiki/Unsupported-Downloads 2.Android studio 旧版本下载 下载地址 https://developer.android.com/studio/archive 如果出现以下页面 点击…

开源存储详解-分布式存储与ceph

ceph体系结构 rados&#xff1a;reliable, autonomous, distributed object storage, rados rados采用c开发 对象存储 ceph严格意义讲只提供对象存储能力&#xff0c;ceph的块存储能力实际是基于对象存储库librados的rbd 对象存储特点 对象存储采用put/get/delete&#xf…

Midjourney Imagine API 使用

Midjourney Imagine API 申请及使用 Midjourney 是一款非常强大的 AI 绘图工具&#xff0c;只要输入关键字&#xff0c;就能在短短一两分钟生成十分精美的图像。Midjourney 以其出色的绘图能力在业界独树一帜&#xff0c;如今&#xff0c;Midjourney 早已在各个行业和领域广泛…

docker从下载到Python项目打包到容器中运行(解决下拉超时问题)

docker安装&#xff08;如果第一步或者第二步没有成功&#xff0c;说明是你的镜像源有问题&#xff0c;私聊我获取镜像源&#xff09;镜像位置_/etc/yum.repos.d/CentOS-Base.repo sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/dock…

运算指令(PLC)

加 ADD 减 SUB 乘 MUL 除 DIV 浮点运算 整数运算

Linux高级--3.2.5 “外挂式”死锁监测设计

一、生活中“死锁”的场景 三个人&#xff0c;甲乙丙&#xff0c; 甲借了丙的钱&#xff0c;丙借了乙的钱&#xff0c;乙借了甲的钱。 甲找乙还钱&#xff0c;乙说&#xff1a;“别人还我 我就还你 ”&#xff0c;甲说&#xff1a;“好&#xff0c;那我等你” 乙找丙还钱&am…

图像去雾 | 基于Matlab的图像去雾系统(四种方法)

图像去雾 | 基于Matlab的图像去雾系统&#xff08;四种方法&#xff09; 目录 图像去雾 | 基于Matlab的图像去雾系统&#xff08;四种方法&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于Matlab的图像去雾系统&#xff08;四种方法&#xff09; 关于图像…