当前位置: 首页 > news >正文

设计模式-职责链+反射

文章目录

  • 前言
  • 简单版本的职责链加反射
  • 职责链反射思路
  • 过程
  • 总结

前言

最近学习设计模式对于职责链的学习有了一些深入的了解故此有了这篇博客

简单版本的职责链加反射

职责链模式(Chain of Responsibility Pattern)和反射(Reflection)是两种不同的设计概念,它们可以结合使用来实现一些灵活的功能。下面是对这两个概念的简要说明和如何结合使用的示例。

职责链模式:
职责链模式是一种行为型设计模式,它通过将请求的发送者和接收者解耦,构成一个接收者链,并沿着这个链传递请求,直到有一个接收者能够处理它。每个接收者都可以选择处理请求或将其传递给下一个接收者。

在职责链模式中,每个接收者都有一个处理方法,用于处理请求。如果接收者无法处理请求,它将把请求传递给下一个接收者,直到找到能够处理请求的接收者,或者请求到达链的末尾。

反射:
反射是指在运行时动态地获取对象的信息,并可以在运行时操作对象。通过反射机制,我们可以获取类的属性、方法和构造函数等信息,并且可以在运行时调用它们。

通过反射,我们可以在不提前知道具体类名的情况下,动态地创建对象、调用方法和访问属性。这种灵活性使得我们可以编写通用的代码,可以应对各种不同的类。

结合使用职责链模式和反射:
在某些场景下,我们可能希望在职责链模式中能够动态地添加或移除接收者,而不需要修改已有的代码。这时,可以使用反射机制来实现。

通过反射,我们可以在运行时动态地创建接收者对象,并将其添加到职责链中。这样,我们就能够实现灵活地配置职责链,而无需硬编码接收者的创建和添加过程。

以下是一个简单示例,演示如何结合职责链模式和反射:

using System;
using System.Reflection;// 定义请求类
class Request
{public string Content { get; set; }
}// 定义抽象处理器
abstract class Handler
{protected Handler NextHandler { get; set; }public void SetNextHandler(Handler handler){NextHandler = handler;}public abstract void HandleRequest(Request request);
}// 具体处理器1
class ConcreteHandler1 : Handler
{public override void HandleRequest(Request request){// 检查是否能够处理请求,如果不能,则传递给下一个处理器if (request.Content.Contains("A")){Console.WriteLine("ConcreteHandler1 处理了请求");}else if (NextHandler != null){NextHandler.HandleRequest(request);}}
}// 具体处理器2
class ConcreteHandler2 : Handler
{public override void HandleRequest(Request request){// 检查是否能够处理请求,如果不能,则传递给下一个处理器if (request.Content.Contains("B")){Console.WriteLine("ConcreteHandler2 处理了请求");}else if (NextHandler != null){NextHandler.HandleRequest(request);}}
}class Program
{static void Main(string[] args){// 使用反射动态创建具体处理器Handler handler1 = CreateHandler("ConcreteHandler1");Handler handler2 = CreateHandler("ConcreteHandler2");// 构建职责链handler1.SetNextHandler(handler2);// 创建请求Request request = new Request { Content = "Test A,B" };// 发送请求到职责链handler1.HandleRequest(request);Console.ReadLine();}// 使用反射动态创建处理器对象static Handler CreateHandler(string handlerName){Assembly assembly = Assembly.GetExecutingAssembly();Type handlerType = assembly.GetType(handlerName);return (Handler)Activator.CreateInstance(handlerType);}
}

在上述示例中,我们使用职责链模式来处理请求,并通过反射动态地创建具体处理器对象。这样,我们就可以根据需要轻松地添加新的处理器,而无需修改已有的代码。

职责链反射思路

这次通过再次学习职责联的模式自己也是收获很多,话不多说直接上干货。

1:都知道职责链的模式是需要设置上下级关系的,这就可以用到一些判断当中,而且是多级判断的,所以我们每一个判断的需求都让它生成一个职责这样就不用把那么的if语句搬出来了。

2:反射的思路,我们可以通过在配置文件中把每个职责的反射写好,然后在单独的写一个反射来,这个反射是干什么的,它的value值是刚刚写好的职责的key值,并且排好序,用符号隔开。

过程

这个是配置文件要准备的事情,这个准备好了就可以直接用了,我们在代码中获取配置文件中写好的那个有对应那些职责链key值的,然后进行切割把它放到一个数组中,要知道把这个值获取 后是一个字符串类型,放入数组的这个过程它的顺序就已经排好了,然后我们通过一个循环可以把这些切割好的字符直接放入反射中就能把那些具体的职责类实例化了,然后设置一个集合接收,这个集合就是这些职责类的父类,前面的工作做完以后就是设置这些类的上下级关系的时候了,也是通过循环的过程设置上下级。

上面这些过程都做完了,那么你的职责链的这个模式更加的灵活了,灵活在哪里呢,就在你的配置文件当中,如果我们在后面想要添加一个新的职责判断,那么我们就不需要再去代码中改了,只需要在配置文件中添加一个新的反射,然后在那个有那些职责Key值的反射中修改一下就好,添加或者修改顺序。

如下:

<add key="T_reviseNew" value="CustomerChange.CustomerChangeNew"/>
<add key="T_reviseOld" value="CustomerChange.CustomerChangeold"/>
<add key="T_chargeK" value="CustomerChange.charge"/> //这三个是具体的职责类,通过反射实例化
<add key="num" value="T_reviseOld,T_chargeK,T_reviseNew"/>  //这个是具体职责链的顺序有这个的出现就把被写死的职责顺序又重新活了,通过反射获取value然后进行切割,而且切割好的这个数组就是按照你写好的这个顺序存放的,只需要循环数组然后通过反射实例化具体的类就好,而你的集合存放顺序也是数组的循环顺序。

具体的代码操作:

        List<CustomerChangeG> list = new List<CustomerChangeG>();//声明一个父类型的集合string str = AbstractFactory.Factory.achieve("num");//通过反射获取写好的职责链顺序string[] sArray = str.Split(',');//切割写好的顺序放入数组foreach (string item in sArray)//循环数组把切割好字符串放入反射进行实例化{list.Add(AbstractFactory.Factory.Dynamic(item));//讲实例化好的职责类放入集合中}for (int i = 0; i < list.Count; i++)//循环集合{var item = list[i];//将具体的类放入这个item中var item1 = list[0];//获取第一个职责链中第一个职责类if (i != list.Count - 1)//判断是不是集合中最后一个类{item.SetSuccessor(item = list[i + 1]);//这里设置上下级}else{item1.HandleRequest(endynamic);//执行职责链}}

最后:职责链的功能很明确,每一个职责都有自己要做的事情,所以用职责链的功能一般是一个连串性的,但是如果我们想添加一个新的职责就会破开开闭原则,但是这个反射的出现就把这个问题解决了,而且以后我们不管添加多少职责都没有问题,又不会更改代码,只需更改配置文件的顺序就行。

总结

结合职责链模式和反射可以带来以下质的变化:

  1. 灵活性增加:通过职责链模式,我们可以轻松地添加、移除或重新排序处理器,而无需修改已有的代码。结合反射,我们可以在运行时动态地创建具体处理器对象,使系统更加灵活,能够适应不同的需求。

  2. 可扩展性提高:使用职责链模式和反射,我们可以将处理器的创建和添加逻辑与具体的业务逻辑解耦。这意味着我们可以在不修改现有代码的情况下,通过添加新的处理器来扩展功能。这种可扩展性使得系统更易于维护和升级。

  3. 可配置性增强:反射允许我们动态地创建对象和调用方法,可以根据配置文件或其他外部数据源来决定职责链中的处理器组成。这样,我们可以在运行时根据需要配置职责链,而无需重新编译和部署应用程序。

  4. 代码复用性提高:通过反射,我们可以编写通用的处理器创建和添加逻辑,使其适用于不同的职责链。这样,我们可以实现代码的复用,减少重复编写类似逻辑的工作。

相关文章:

设计模式-职责链+反射

文章目录 前言简单版本的职责链加反射职责链反射思路过程总结 前言 最近学习设计模式对于职责链的学习有了一些深入的了解故此有了这篇博客 简单版本的职责链加反射 职责链模式&#xff08;Chain of Responsibility Pattern&#xff09;和反射&#xff08;Reflection&#x…...

Middleware ❀ Kafka功能与使用详解

文章目录 1. 概述1.1. 消息队列1.2. 应用场景1.3. 工作模式1.4. 基础结构1.4.1. 结构组件1.4.2. 数据同步1.4.3. ACK机制1.4.4. 分区机制1.4.4.1. 使用Partition Key写入1.4.4.2. 轮询写入 - 默认规则1.4.4.3. 指定Partition写入 1.4.5. Offset偏移量1.4.5.1. 消息顺序性1.4.5.…...

python3.11教程1:python基础语法、程序控制、函数

文章目录 一、Python简介1.1 为什么学习python1.2 python安装与配置1.3 python解释器1.4 命令行参数1.4.1 sys.argv变量1.4.2 -c和-m选项 1.5 解释器的运行环境1.5.1 编码格式1.5.2 编码声明 二、Python基础语法2.1 行结构2.2 变量&#xff08;标识符&#xff09;2.3 字节串2.4…...

【C++】关于using namepace xxx 使用命名空间和冲突

官方定义 namespace是指 标识符的各种可见范围。命名空间用关键字namespace来定义。 命名空间是C的一种机制&#xff0c;用来把单个标识符下的大量有逻辑联系的程序实体组合到一起。此标识符作为此组群的名字。 基本使用 编译及执行命令&#xff1a; g test.cpp -o test ./…...

Linux常用命令——cupsenable命令

在线Linux命令查询工具 cupsenable 启动指定的打印机 补充说明 cupsenable命令用于启动指定的打印机。 语法 cupsenable(选项)(参数)选项 -E&#xff1a;当连接到服务器时强制使用加密&#xff1b; -U&#xff1a;指定连接服务器时使用的用户名&#xff1b; -u&#xff…...

基于Stable Diffusion的AIGC服饰穿搭实践

本文主要介绍了基于Stable Diffusion技术的虚拟穿搭试衣的研究探索工作。文章展示了使用LoRA、ControlNet、Inpainting、SAM等工具的方法和处理流程&#xff0c;并陈述了部分目前的实践结果。通过阅读这篇文章&#xff0c;读者可以了解到如何运用Stable Diffusion进行实际操作&…...

【 ARMv9 Cluster BUS QoS 配置】

文章目录 ARM Cluster QoS ARM Cluster QoS QoS&#xff08;Quality of Service&#xff0c;服务质量&#xff09;在 ARM 架构中&#xff0c;主要指的是一种机制&#xff0c;它可以控制和管理系统资源&#xff08;如内存、总线带宽等&#xff09;的使用&#xff0c;以满足各种…...

简单了解网络基本概念

目录 一、网络含义 二、什么是以太网&#xff1f; 三、网络分类 四、网络架构 五、数据传输方式 六、双工模式 一、网络含义 在实际生活中我们用传输介质把独立的终端设备相互连接起来就构成了网络。 二、什么是以太网&#xff1f; 以太网是一种网络通信协议标准&#…...

网络安全知识库

0x00 前言 本篇用来整理所有的零散的知识&#xff0c;作为一个技能树或者技能表来进行引导 CTF 加解密合集CTF Web合集 0x01 Http 1.http头 1.1 本地访问识别 如何伪造http头&#xff0c;让后端认为是本地访问...

无涯教程-JavaScript - FLOOR函数

描述 FLOOR函数将数字向下舍入为零,直到最接近的有效倍数。 语法 FLOOR (number, significance)争论 Argument描述Required/OptionalNumberThe numeric value you want to round.RequiredSignificanceThe multiple to which you want to round.Required Notes 如果数字的符…...

【LeetCode-中等题】146. LRU 缓存

文章目录 题目方法一&#xff1a;直接继承LinkedHashMap调用api方法二&#xff1a;自定义LinkedHashMap HashMap ListNode LinkedHashMap 题目 LRU缓存是什么&#xff1a;LRU缓存机制&#xff0c;你想知道的这里都有 实现 LRU 缓存算法 方法一&#xff1a;直接继承Linked…...

表白墙程序

目录 一、页面代码部分 二、设计程序 二、实现 doPost​编辑 三、实现 doGet 四、前端代码部分 五、使用数据库存储数据 一、页面代码部分 在之前的一篇博客中&#xff0c;已经写过了表白墙的页面代码实现&#xff0c;这里就不再重复了 页面代码如下&#xff1a; <!…...

git 本地仓库关联到远程仓库

将本地仓库关联到远程仓库 方式一&#xff1a;远程仓库没有文件 第一步&#xff1a; git init&#xff08;初始化git仓库&#xff09; 第二步&#xff1a; git remote add 地址&#xff08;设置remote地址&#xff09; 第三步&#xff1a; git add . &#xff08;将所有变…...

Introducing Language Guidance in Prompt-based Continual Learning

本文是LLM系列文章&#xff0c;针对《Introducing Language Guidance in Prompt-based Continual Learning》的翻译。 基于提示的持续学习中引入语言指导 摘要1 引言2 相关工作3 背景4 基于提示的持续学习语言指导5 实验6 结论 摘要 持续学习旨在学习一系列任务的单一模型&am…...

Matlab(数值微积分)

目录 1.多项式微分与积分 1.1 微分 1.2 多项式微分 1.3 如何正确的使用Matlab? 1.3.1 Matlab表达多项式 1.3.2 polyval() 多项式求值 1.3.3 polyder()多项式微分 1.4 多项式积分 1.4.1 如何正确表达 1.4.2 polyint() 多项式积分 2.数值的微分与积分 2.1 数值微分 2…...

【数据结构回顾】

数据结构回顾 一、单链表二、单循环链表 一、单链表 #include <stdio.h> #include <stdlib.h>typedef struct Node {int data;Node *next; }Node;Node* initList() {Node *list (Node*)malloc(sizeof(Node));list->data 0;list->next NULL;return list; }…...

QT创建可移动点类

效果如图所示&#xff1a; 创建新类MovablePoint&#xff0c;继承自QWidget. MovablePoint头文件: #ifndef MOVABLEPOINT_H #define MOVABLEPOINT_H#include <QWidget> #include <QPainter> #include <QPaintEvent> #include <QStyleOption> #includ…...

Flutter启动页

效果图 import dart:async; import package:flutter/cupertino.dart; import package:flutter/material.dart; import jumpPage.dart;class TransitPage extends StatefulWidget {const TransitPage({super.key});overrideState<TransitPage> createState() > _Trans…...

读word模板批量生成制式文件

文章目录 1、Maven依赖2、.docx或.doc格式的word模板准备3、读word模板&#xff0c;批量替换代码域&#xff0c;生成文件&#xff0c;demo4、结果展示 1、Maven依赖 <dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagre…...

Node.js crypto模块 加密算法

背景 微信小程序调用飞蛾热敏纸打印机&#xff0c;需要进行参数sig签名校验&#xff0c;使用的是sha1进行加密 // 通过crypto.createHash()函数&#xff0c;创建一个hash实例&#xff0c;但是需要调用md5&#xff0c;sha1&#xff0c;sha256&#xff0c;sha512算法来实现实例的…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...

UE5 音效系统

一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类&#xff0c;将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix&#xff0c;将上述三个类翻入其中&#xff0c;通过它管理每个音乐…...

ZYNQ学习记录FPGA(二)Verilog语言

一、Verilog简介 1.1 HDL&#xff08;Hardware Description language&#xff09; 在解释HDL之前&#xff0c;先来了解一下数字系统设计的流程&#xff1a;逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端&#xff0c;在这个过程中就需要用到HDL&#xff0c;正文…...