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

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.mzph.cn/web/64875.shtml

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

相关文章

在K8S中,如何部署kubesphere?

在Kubernetes集群中&#xff0c;对于一些基础能力较弱的群体来说K8S控制面板操作存在一定的难度&#xff0c;此时kubesphere可以有效的解决这类难题。以下是部署kubesphere的操作步骤&#xff1a; 操作部署&#xff1a; 1. 部署nfs共享存储目录 yum -y install nfs-server e…

CSS系列(43)-- Anchor Positioning详解

前端技术探索系列&#xff1a;CSS Anchor Positioning详解 &#x1f3af; 致读者&#xff1a;探索智能定位的艺术 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 CSS Anchor Positioning&#xff0c;这个强大的元素定位特性。 基础概念 &#x1f680; 锚点设…

Python判别不同平台操作系统调用相应的动态库读写NFC

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bV0E4YV&ftt&id615391857885 import sys import struct # struct的pack函数把任意数据类型变成字符串 import ctypes # 调用DLL动态库要有这个引用if sys.platform…

树莓派之旅-第一天 系统的烧录和设置

自言自语&#xff1a; 在此记录一下树莓派的玩法。以后有钱了买点来玩啊草 系统的安装烧录 系统下载 树莓派官网&#xff1a;https://www.raspberrypi.com/ 首页点击SoftWare进入OS下载页面 这里是安装工具&#xff1a;安装工具负责将系统镜像安装到sd卡中 点击下载符合自己…

商用车自动驾驶,迎来大规模量产「临界点」?

商用车自动驾驶&#xff0c;正迎来新的行业拐点。 今年初&#xff0c;交通部公开发布AEB系统运营车辆标配征求意见稿&#xff0c;首次将法规限制条件全面放开&#xff0c;有望推动商用车AEB全面标配&#xff0c;为开放场景的商用车智能驾驶市场加了一把火。 另外&#xff0c;…

人工智能及深度学习的一些题目

1、一个含有2个隐藏层的多层感知机&#xff08;MLP&#xff09;&#xff0c;神经元个数都为20&#xff0c;输入和输出节点分别由8和5个节点&#xff0c;这个网络有多少权重值&#xff1f; 答&#xff1a;在MLP中&#xff0c;权重是连接神经元的参数&#xff0c;每个连接都有一…

Solon 加入 GitCode:助力国产 Java 应用开发新飞跃

在当今数字化快速发展的时代&#xff0c;Java 应用开发框架不断演进&#xff0c;开发者们始终在寻找更快、更小、更简单的解决方案。近期&#xff0c;Solon 正式加入 GitCode&#xff0c;为广大 Java 开发者带来全新的开发体验&#xff0c;尤其是在国产应用开发进程中&#xff…

VScode 只能运行c,运行不了c++的解决问题

原文链接&#xff1a;Vscode只能运行c&#xff0c;运行不了c的解决方法 VScode 只能运行c&#xff0c;运行不了c&#xff0c;怎么回事呢&#xff0c;解决问题&#xff1a; 在tasks.json中加上“"-lstdc"”&#xff0c; 这样之后 要重启VScode&#xff0c;点击链接…

Ansible Jinja2 语法简介及使用

1、Jinja2 介绍 Jinja2 是基于 python 的模板引擎&#xff0c;功能比较类似于 PHP 的 smarty&#xff0c;J2ee 的 Freemarker和velocity。它能完全支持unicode&#xff0c;并具有集成的沙箱执行环境&#xff0c;应用广泛。 jinja2使用BSD授权 Jinja2的语法是由 variables(变量…

SpringCloud系列教程:微服务的未来 (五)枚举处理器、JSON处理器、分页插件实现

在现代 Java 开发中&#xff0c;我们常常需要处理各种通用的功能和需求&#xff0c;诸如枚举的处理、JSON 数据处理&#xff0c;以及分页查询等。这些功能虽然看似简单&#xff0c;但在实际开发中往往涉及到许多细节和优化。为了提高开发效率、减少重复代码的编写&#xff0c;我…

游戏引擎学习第69天

回顾碰撞响应时我们停留的位置 从昨天的讨论开始&#xff0c;我们正准备处理碰撞响应的复杂性。具体来说&#xff0c;我们讨论的是&#xff0c;当两个实体在屏幕上发生碰撞时&#xff0c;如何回应这种情况。碰撞本身并不复杂&#xff0c;但要处理其后的反应和规则则更具挑战性…

【Linux】信号处理

一、Linux系统信号 1、常见的系统信号 常见的Linux系统信号 信号值描述1SIGHUP挂起&#xff08;hang up&#xff09;进程2SIGINT中断进&#xff08;interrupt&#xff09;程3SIGQUIT停止&#xff08;stop&#xff09;进程9SIGKILL无条件终止&#xff08;terminate&#xff09;…

开源模型应用落地-qwen2-7b-instruct-LoRA微调-Axolotl-单机多卡-RTX 4090双卡(七)

一、前言 本篇文章将使用Axolotl去高效微调QWen2系列模型,通过阅读本文,您将能够更好地掌握这些关键技术,理解其中的关键技术要点,并应用于自己的项目中。 二、术语介绍 2.1. LoRA微调 LoRA (Low-Rank Adaptation) 用于微调大型语言模型 (LLM)。 是一种有效的自适应策略,…

数据结构与算法学习笔记----快速幂

数据结构与算法学习笔记----快速幂 author: 明月清了个风 first publish time: 2025.1.2 ps⭐️快速幂的两道模版题&#xff0c;快速幂&#xff0c;乘法逆元&#xff0c;费马小定理 Acwing 875. 快速幂 [原题链接](875. 快速幂 - AcWing题库) 给定 n n n组 a i , b i , p i…

爬虫代码中如何添加异常处理?

在编写爬虫代码时&#xff0c;添加异常处理是非常重要的一步&#xff0c;因为它可以帮助我们处理网络请求中可能出现的各种问题&#xff0c;比如网络连接错误、超时、解析错误等。以下是如何在Python爬虫代码中添加异常处理的示例&#xff1a; import requests from bs4 impor…

MAC环境安装(卸载)软件

MAC环境安装&#xff08;卸载&#xff09;软件 jdknode安装node&#xff0c;并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净&#xff0c;可以再细分删除验证删除结果 jdk 1.下载jdk 先去官网下载自己需要的版…

本地LLM部署--llama.cpp

–图源GitHub项目主页 概述 llama.cpp是以一个开源项目&#xff08;GitHub主页&#xff1a;llamma.cpp&#xff09;&#xff0c;也是本地化部署LLM模型的方式之一&#xff0c;除了自身能够作为工具直接运行模型文件&#xff0c;也能够被其他软件或框架进行调用进行集成。 其…

uniapp中使用ruoyiPlus中的加密使用(crypto-js)

package.json中添加 "crypto-js": "^4.2.0", "jsencrypt": "^3.3.2",但是vue2中使用 import CryptoJS from cryptojs; 这一步就会报错 参照 参照这里&#xff1a;vue2使用CryptoJS实现信息加解密 根目录下的js文档中新增一个AESwork.…

go项目使用gentool生成model的gen.go问题

Gen Tool 是一个没有依赖关系的二进制文件&#xff0c;可以用来从数据库生成结构。 使用方法&#xff1a; go install gorm.io/gen/tools/gentoollatest在项目根目录,执行连接的数据库中指定某几张表结构生成数据库model层 gentool -dsn "root:123456tcp(localhost:330…

路由基本配置实验

路由器用于实现不同类型网络之间的互联。 路由器转发ip分组的基础是路由表。 路由表中的路由项分为直连路由项、静态路由项和动态路由项。 通过配置路由器接口的ip地址和子网掩码自动生成直连路由项。 通过手工配置创建静态路由项。 热备份路由器协议允许将由多个路由器组…