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

设计模式—职责链模式(Chain of Responsibility)

目录

思维导图

什么是职责链模式?

有什么优点呢?

有什么缺点呢?

什么场景使用呢?

代码展示

①、职责链模式

②、加薪代码重构


思维导图

什么是职责链模式?

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

我要请假一个月,我发送审批给纪委,但是纪委只能批两小时以内的假,没有权限批假一个月,就需要转交给纪老师,纪老师也没有权限批假一个月,就转交给米老师,这时米老师说“好,准假了”。

这里一层一层的审批就像一条职责链,一个链条,逐层转交自己的请求。

Handler:定义一个处理请示的接口。

ConcreteHandler1:具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理它,否则就将该请求转发给它的后继者。

有什么优点呢?

  • 减少类和类之间的联系,降低耦合;
  • 满足迪米特法则

有什么缺点呢?

  • 中介者可能会很多,很复杂

什么场景使用呢?

  • 有多个对象可以处理同一个请求
  • 在不明确指定接收者的情况下,向多个对象中的提交请求
  • 可动态指定一组对象处理请求


代码展示

场景:

①、职责链模式

Handler类,定义一个处理请示的接口

abstract class Handler
{protected Handler successor;public void SetSuccessor(Handler successor)         //设置继任者{this.successor = successor;}public abstract void HandleRequest(int request);    //处理请求的抽象方法
}

ConcreteHandler1类,具体处理者类

class ConcreteHandler1 : Handler
{public override void HandleRequest (int request){if(request >=0 && request < 10)         //0到10,处理此请求{Console.WriteLine("{0} 处理请求 {1}", this.GetType().Name, request);}else if(successor != null){successor.HandleRequest(request);    //转移到下一位}}
}

ConcreteHandler2类

class ConcreteHandler2 : Handler
{public override void HandleRequest(int request){if (request >= 10 && request < 20)         //0到10,处理此请求{Console.WriteLine("{0} 处理请求 {1}", this.GetType().Name, request);}else if (successor != null){successor.HandleRequest(request);    //转移到下一位}}
}

客户端代码

Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);                              //设置职责链的上家与下家
h2.SetSuccessor(h3);int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };foreach (int request in requests)                 //循环给最小处理者提交请求,不同的数额,有不同权限处理者处理
{h1.HandleRequest(request);
}Console.ReadKey();

②、加薪代码重构

Request类,申请

class Request
{//申请类别private string requestType;public string RequestType{get { return requestType; }set { requestType = value; }}//申请内容private string requestContent;public string RequestContent{get { return requestContent; }set { requestContent = value; }}//数量private int number;public int Number{get { return number; }set { number = value; }}
}

Manager类,管理者

abstract class Manager
{protected string name;//管理者的上级protected Manager superior;public Manager(string name){this.name = name;}//设置管理者的上级public void SetSuperior(Manager superior){this.superior = superior;}//申请请求abstract public void RequestApplications(Request request);
}

CommonManager类,经理

class CommonManager : Manager
{public CommonManager(string name) : base(name) { }public override void RequestApplications(Request request){if (request.RequestType == "请假" && request.Number <= 2){Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);}else{if (superior != null){superior.RequestApplications(request);}}}
}

Majordomo类,总监

class Majordomo : Manager
{public Majordomo(string name) : base(name) { }public override void RequestApplications(Request request){if (request.RequestType == "请假" && request.Number <= 5){Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);}else{if (superior != null){superior.RequestApplications(request);}}}
}

GeneralManager类,总经理

class GeneralManager : Manager
{public GeneralManager(string name) : base(name) { }public override void RequestApplications(Request request){if (request.RequestType == "请假" && request.Number <= 5){Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);}else if (request.RequestType == "加薪" && request.Number <= 500){Console.WriteLine("{0}:{1} 数量{2} 被批准", name, request.RequestContent, request.Number);}else if (request.RequestType == "加薪" && request.Number > 500){Console.WriteLine("{0}:{1} 数量{2} 再说吧", name, request.RequestContent, request.Number);}}
}

客户端代码

 CommonManager jinli = new CommonManager("金利");
Majordomo zongjian = new Majordomo("宗剑");
GeneralManager zhongjingli = new GeneralManager("钟精励");
jinli.SetSuperior(zongjian);
zongjian.SetSuperior(zhongjingli);Request request = new Request();
request.RequestType = "请假";
request.RequestContent="小菜请假";
request.Number = 1;
jinli.RequestApplications(request);Request request2 = new Request();
request2.RequestType = "请假";
request2.RequestContent = "小菜请假";
request2.Number = 4;
jinli.RequestApplications(request2);Request request3 = new Request();
request3.RequestType = "加薪";
request3.RequestContent = "小菜请求加薪";
request3.Number = 500;
jinli.RequestApplications(request3);Request request4 = new Request();
request4.RequestType = "加薪";
request4.RequestContent = "小菜请求加薪";
request4.Number = 1000;
jinli.RequestApplications(request4);Console.ReadKey();


涉及到的知识点

1、一个类里面有哪些东西?

2、类和实例

什么是类?

就是具有相同的属性和功能的对象的抽象的集合。注意:

  • 类名称首字母大写。多个单词则各个首字母大写;
  • 对外公开的方法需要用‘public’修饰符。

什么是实例?

就是一个真实的对象。比如我们都是‘人’,而你和我其实就是‘人’类的实例了。

什么是实例化?

创建对象的过程,使用new关键字来创建。

Cat cat = new Cat();     //其实做了两件事情Cat cat;          //第一步、声明一个Cat的对象,对象名为cat
cat = new Cat();  //第二步、将此cat对象实例化

3、字段和属性

什么是字段?

是存储类要满足其设计所需要的数据,字段是与类相关的变量。

private  string  name = "";     //name就是一个字段,私有的类变量

注意

  • 如果在定义字段时,在字段的类型前面使用了readonly关键字,那么字段就为只读字段,它只能在以下两个位置被赋值或者传递到方法中被改变。
  • 在定义字段时赋值;
  • 在类的构造函数内被赋值,或传递到方法中被改变,而且在构造函数中可以被多次赋值。

属性是什么?

是一个方法或一对方法体。提供对类或对象的访问。

属性怎么用呢?

它有两个方法get和set。

get访问器:从属性获取值。返回与声明的属性相同的数据类型,表示的意思是调用时可以得到内部字段的值或引用;

set访问器:为属性赋值。没有显式设置参数,但它有一个隐式参数,用关键字value表示,它的作用是调用属性时可以给内部的字段或引用赋值。

属性有什么作用?

限制外部类对类中成员的访问权限,定义在类级别上。

private int _age;          //年龄
public int Age                    
{get                    //也可以直接在属性中进行判断操作、设置限制{if (_age >= 0 && _age <= 150)     //如果年龄大于 0并且小于150的,(表示输入正确){return _age;                  //则返回输入的年龄}else                              //否则,(表示输入错误){return 18;                    //返回指定年龄18}}set { _age = value; }
}

静态属性是什么?

在属性前面加static关键字,这个属性就成为了静态属性。

有什么作用呢?

  • 不管类是否有实例,它们都是存在的。
  • 当从类的外部访问时,必须使用类名引用,而不是实例名。
class Person
{private static  string name;   //字段public static string Name      //属性{get { return name; }set { name = value; }}
}
static void Main(string[] args)
{Person.Name = "小菜";      //不需要实例化Person类即可直接对属性赋值
}

属性和字段的公有部分解释:

内存:

  • 字段:分配内存
  • 属性:不分配内存

命名规范:

  • 字段:Camel大小写
  • 属性:Pascal小写

4、修饰符

在变量前面可以加上访问修饰符(readonly、static)

readonly(只读):读取该字段的值不能给字段赋值

static:静态字段,可以直接通过类名访问该字段

5、访问修饰符有哪些?

  • public:公有的,对任何类可访问
  • private:私有的,只在类的内部可以访问,成员默认是这个
  • protected:保护的,只允许该类的派生类访问
  • internal:内部的,同一项目所有类可访问                

6、this关键字传递的是什么?

  • 用于区分类的成员和本地变量或参数;
  • 作为调用方法的实参                
//this调用成员变量或成员方法
class Person
{private string name;               //字段public void setName(string name)    //方法{this.name = name;       //将参数值赋予类中的成员变量}//成员变量和setName()方法中的形式参数的名称相同,都为name,那么如何区分使用的是哪一个变量呢?//使用this关键字代表本类对象的引用,this.name指Person类中name成员变量,等号后面的name指传过来的形参name
}
this作为方法的返回值
public Book getBook()
{return this;                 //返回Book类引用
}在getBook()类中,方法的返回值为Book类,所以方法体中使用return this这种形式将Book类的对象返回

this关键字和对象之间有什么关系?

this引用的就是本类的一个对象。

如果省略this会怎么样?

直接写成name=name,只是把形参name赋值给参数变量本身而已,成员变量name的值没有改变            

7、构造方法

  • 什么时候用?就是对类进行初始化(在创建该类的对象时就会调用)。
  • 有哪些特点?与类同名

     无返回值

     不需要void,在new时候调用      

//希望每个小猫一诞生就有姓名
class Cat
{private string name ="";        //声明Cat类的私有字符串变量namepublic Cat(string name)         //定义Cat类的构造方法,参数是输入一个字符串{this.name =name;            //将参数赋值给私有变量name}public string Shout(){return "我的名字叫"+name+" 喵";}
}

注:所有类都有构造方法,如果你不编码则系统默认生成空的构造方法,若有定义的构造方法,那么默认的构造方法就会失效(这个构造方法什么也不做,只是为了让用户能够顺利地实例化)

8、方法重载

是什么?指方法名相同,但参数的数据类型、个数或顺序不同的方法。(一同二不同)

有什么好处?在不改变原方法的基础上,新增功能。

class Animal
{private string name;//方法重载:方法名相同、数据类型、个数/顺序不同public Animal(){}          //无参的构造方法public Animal(string name) //有参的构造方法{this.name = name;}
}

9、抽象类

什么是抽象类?

目的:抽取相同代码,实现封装思想

特点:

  • 抽象类不能实例化;
  • 抽象方法是必须被子类重写的方法;
  • 如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其他一般方法

什么是重写?

将父类实现替换为它自己的实现

虚成员

抽象成员

关键字

virtual

abstract

实现体

有实现体

没有实现体,被分号取代

在派生类中被覆写

可重写,也可不重写,使用override

必须被重写,使用override

10、六大原则

六大原则

11、六大关系

六大关系

相关文章:

设计模式—职责链模式(Chain of Responsibility)

目录 思维导图 什么是职责链模式&#xff1f; 有什么优点呢&#xff1f; 有什么缺点呢&#xff1f; 什么场景使用呢&#xff1f; 代码展示 ①、职责链模式 ②、加薪代码重构 思维导图 什么是职责链模式&#xff1f; 使多个对象都有机会处理请求&#xff0c;从而避免请…...

vue小测试之拖拽、自定义事件

在开始之前我去复习了一下&#xff0c;clientX、clientY、pageX、pageY的区别&#xff0c;对于不熟悉offsetLeft和offsetTop的也可以在这里去复习一下。 vue拖拽指令之offsetX、clientX、pageX、screenX_wade3po的博客-CSDN博客_vue offset 客户区坐标位置&#xff08;clientX&…...

时序预测 | MATLAB实现DBN-SVM深度置信网络结合支持向量机时间序列预测(多指标评价)

时序预测 | MATLAB实现DBN-SVM深度置信网络结合支持向量机时间序列预测(多指标评价) 目录 时序预测 | MATLAB实现DBN-SVM深度置信网络结合支持向量机时间序列预测(多指标评价)效果一览基本描述程序设计参考资料 效果一览 基本描述 MATLAB实现DBN-SVM深度置信网络结合支持向量机…...

Python中异步编程是什么意思? - 易智编译EaseEditing

异步编程是一种编程模式&#xff0c;用于处理可能会导致程序等待的操作&#xff0c;例如网络请求、文件读写或长时间的计算任务&#xff0c;而不会阻塞整个程序的执行。 在传统的同步编程中&#xff0c;当程序执行一个耗时的操作时&#xff0c;它会等待该操作完成&#xff0c;…...

【JS真好玩】自动打字机效果

目录 一、前言二、布局分析三、总体样式四、中间部分五、底部5.1 div5.2 label5.3 input 六、JS让它动起来6.1定时器6.2 字符串处理6.2.1 slice6.2.2 splice6.3.3 split 七、总结 一、前言 大家好&#xff0c;今天实现一个自动打字机效果&#xff0c;旨在实现一些网上很小的de…...

宠物赛道,用AI定制宠物头像搞钱项目教程

今天给大家介绍一个非常有趣&#xff0c;而粉丝价值又极高&#xff0c;用AI去定制宠物头像或合照的AI项目。 接触过宠物行业应该知道&#xff0c;获取1位铲屎官到私域&#xff0c;这类用户的价值是极高的&#xff0c;一个宠物粉&#xff0c;是连铲个屎都要花钱的&#xff0c;每…...

基于vue和element的脚手架【vue-element-admin 和vue-element-plus-admin 】

vue-element-admin vue-element-admin 是一个后台前端解决方案&#xff0c;它基于 vue 和 element-ui实现 介绍 | vue-element-adminA magical vue adminhttps://panjiachen.github.io/vue-element-admin-site/zh/guide/ vue-element-plus-admin vue-element-plus-admin 是一…...

推荐Java开发常用的工具类库google guava

Guava Guava是一个Google开源的Java核心库&#xff0c;它提供了许多实用的工具和辅助类&#xff0c;使Java开发更加简洁、高效、可靠。目前和hutool一起&#xff0c;是业界常用的工具类库。shigen也比较喜欢使用&#xff0c;在这里列举一下常用的工具类库和使用的案例。 参考…...

stencilJs学习之构建 Drawer 组件

前言 在之前的学习中&#xff0c;我们已经掌握了 stencilJs 中的一些核心概念和基础知识&#xff0c;如装饰器 Prop、State、Event、Listen、Method、Component 以及生命周期方法。这些知识是构建复杂组件和应用的基础&#xff0c;而抽屉组件是一个很好的示例&#xff0c;能够…...

hbase 国内镜像 极速下载

文章目录 国内镜像汇总-极速下载【JavaPub版】 lucene国内镜像 https://mirrors.cloud.tencent.com/apache/hbase/ 国内镜像汇总-极速下载【JavaPub版】...

Linux驱动——Tiny4412芯片_Source Insight的下载+Linux3.5内核下工程的创建

文章目录 前言Source Insight的下载1.下载地址2.下载步骤 linux3.5内核下工程的创建 前言 本博客仅作为笔记总结&#xff0c;以及帮助有需要的人&#xff0c;不作权威解释。 Source Insight的下载 1.下载地址 官网&#xff1a;https://www.sourceinsight.com/ 另外可以选择…...

rust交叉编译 在mac下编译linux和windows

系统版本macbook proVentura 13.5linux ubuntu22.04.3 LTS/18.04.6 LTSwindowswindows 10 专业版 20H2mac下rustc --versionrustc 1.74.0-nightly (58eefc33a 2023-08-24)查看当前系统支持的交叉编译指定系统版本列表 rustup target list如果已经安装这里会显示(installed)。…...

linux离线环境安装redis

先检查gcc版本&#xff0c;使用gcc --version进行检查&#xff0c;版本在5以下的&#xff0c;安装redis要安装redis6以下的版本 如果没有gcc命令&#xff0c;要先安装gcc命令。因为是离线环境&#xff0c;yum命令什么的用不了。为了安装gcc&#xff0c;进行了几种尝试。 1、下…...

记录学习--字节码解析try catch

1.示例代码 Testpublic void someTest() {String s "111";try {s "222";int i 1/0;} catch (Exception e){e.printStackTrace();System.out.println(s);}System.out.println(s);}2.示例代码对应的字节码 0 ldc #2 <111>2 astore_13 ldc #3 <22…...

多线程与高并发——并发编程(3)

文章目录 三、锁1 锁的分类1.1 可重入锁、不可重入锁1.2 乐观锁、悲观锁1.3 公平锁、非公平锁1.4 互斥锁、共享锁2 深入synchronized2.1 类锁、对象锁2.2 synchronized的优化2.3 synchronized实现原理2.4 synchronized的锁升级2.5 重量级锁底层 ObjectMonitor3 深入ReentrantLo…...

关于内网主备+https

先openssl证书 整体流程为&#xff1a; 1、页面访问为https&#xff0c;在电脑修改hosts文件&#xff0c;如域名为 babaozhou.com, 则配置为 ip1 babaozhou.com&#xff0c;ip2 babaozhou.com&#xff1b; 也就是说同域名关联两个ip&#xff0c;这样如果服务器1ping不通了则可…...

java入坑之网络编程

一、 网络基础知识 1.1网卡 1.2IP地址 1.3端口 1.4保留IP 1.5网络协议 二、UDP 编程 2.1相关概念 计算机通讯&#xff1a;数据从一个IP的port出发&#xff08;发送方&#xff09;&#xff0c;运输到另外一个IP的port&#xff08;接收方&#xff09; UDP&#xff1a;无连接无…...

A Survey on Large Language Model based Autonomous Agents

本文是LLM系列的文章&#xff0c;针对《A Survey on Large Language Model based Autonomous Agents》的翻译。 基于大模型的自动agents综述 摘要1 引言2 基于LLM的自动代理构建3 基于LLM的自动代理应用4 基于LLM的自动代理评估5 相关综述6 挑战6.1 角色扮演能力6.2 广义与人对…...

Integer、Long 等包装类 == 值判断、地址判断与缓存

先看下以下代码和输出 public static void main(String[] args) throws Exception{Integer a-128;Integer aa-128;System.out.printf("aaa? %s \n",aaa);Integer b127;Integer bb127;System.out.printf("bbb? %s \n",bbb);Integer c128;Integer cc128;Sy…...

numpy学习:reshape和resize

.reshape 与 .resize reshape&#xff1a;有返回值&#xff0c;所谓有返回值&#xff0c;即不对原始多维数组进行修改&#xff1b; resize&#xff1a;无返回值&#xff0c;所谓无返回值&#xff0c;即会对原始多维数组进行修改&#xff1b;...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

自然语言处理——文本分类

文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益&#xff08;IG&#xff09; 分类器设计贝叶斯理论&#xff1a;线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别&#xff0c; 有单标签多类别文本分类和多…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...