设计模式—职责链模式(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)
目录 思维导图 什么是职责链模式? 有什么优点呢? 有什么缺点呢? 什么场景使用呢? 代码展示 ①、职责链模式 ②、加薪代码重构 思维导图 什么是职责链模式? 使多个对象都有机会处理请求,从而避免请…...

vue小测试之拖拽、自定义事件
在开始之前我去复习了一下,clientX、clientY、pageX、pageY的区别,对于不熟悉offsetLeft和offsetTop的也可以在这里去复习一下。 vue拖拽指令之offsetX、clientX、pageX、screenX_wade3po的博客-CSDN博客_vue offset 客户区坐标位置(clientX&…...

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

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

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

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

基于vue和element的脚手架【vue-element-admin 和vue-element-plus-admin 】
vue-element-admin vue-element-admin 是一个后台前端解决方案,它基于 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核心库,它提供了许多实用的工具和辅助类,使Java开发更加简洁、高效、可靠。目前和hutool一起,是业界常用的工具类库。shigen也比较喜欢使用,在这里列举一下常用的工具类库和使用的案例。 参考…...

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

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

Linux驱动——Tiny4412芯片_Source Insight的下载+Linux3.5内核下工程的创建
文章目录 前言Source Insight的下载1.下载地址2.下载步骤 linux3.5内核下工程的创建 前言 本博客仅作为笔记总结,以及帮助有需要的人,不作权威解释。 Source Insight的下载 1.下载地址 官网: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版本,使用gcc --version进行检查,版本在5以下的,安装redis要安装redis6以下的版本 如果没有gcc命令,要先安装gcc命令。因为是离线环境,yum命令什么的用不了。为了安装gcc,进行了几种尝试。 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证书 整体流程为: 1、页面访问为https,在电脑修改hosts文件,如域名为 babaozhou.com, 则配置为 ip1 babaozhou.com,ip2 babaozhou.com; 也就是说同域名关联两个ip,这样如果服务器1ping不通了则可…...

java入坑之网络编程
一、 网络基础知识 1.1网卡 1.2IP地址 1.3端口 1.4保留IP 1.5网络协议 二、UDP 编程 2.1相关概念 计算机通讯:数据从一个IP的port出发(发送方),运输到另外一个IP的port(接收方) UDP:无连接无…...

A Survey on Large Language Model based Autonomous Agents
本文是LLM系列的文章,针对《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:有返回值,所谓有返回值,即不对原始多维数组进行修改; resize:无返回值,所谓无返回值,即会对原始多维数组进行修改;...

JPA在不写sql的情况下实现模糊查询
本文已收录于专栏 《Java》 目录 背景介绍概念说明单字段模糊匹配:多字段模糊匹配: 实现过程代码实现1.写一个实体类去实现Specification接口,重写toPredicate方法2.定义一个接口去继承JpaRepository接口,并指定返回的类型和参数类…...

Java设计模式之单例模式
单例模式是一种设计模式,它的目的是确保一个类只有一个实例,并提供一个全局访问点来访问该实例。这个模式通常在需要控制资源访问权、限制实例化数量或实现全局共享时使用。 在实现单例模式时,一般会定义一个私有的构造函数,以防…...

Vue3 学习
基础 js:https://www.bilibili.com/video/BV15T411j7pJ/?spm_id_from333.337.search-card.all.click&vd_source9747207be61edfe4ec62226fc79b3589 官方文档: https://cn.vuejs.org/ 版本之间差异在关于---》版本发布 https://cn.vuejs.org/about/release…...

Error obtaining UI hierarchy Error taking device screenshot: EOF/NULL 解决办法
RT:Error obtaining UI hierarchy Error taking device screenshot: EOF/NULL 解决办法 关于monitor开发神器我就不多说了,但是假如我们在开发中遇到如上问题该怎么处理呢?别慌下面会有方法,不过不是对任何机型都有效,…...

Java框架之王:Spring的崛起与进化
在Java世界中,Spring框架无疑已经成为了一个传奇。它为开发者提供了强大的工具和丰富的功能,使得构建高质量、可扩展的Java应用程序变得轻松便捷。本文将带您领略Spring的魅力,以及它在过去几年中的崛起和进化。 一、Spring的崛起 Spring框…...

【位运算】位运算常用技巧总结
目录 前言 一.常见的小问题 1.给定一个数n,确定它的二进制表示中的第x位是0还是1 2.给定一个数n,将它的二进制表示中的第x位修改成1 3.给定一个数n,将它的二进制表示中的第x位修改成0 4.给定一个数n,提取它的二进制表示中最右侧的1&…...

【STM32】IIC使用中DMA传输时 发送数据总少一个的问题
问题描述 在使用STM32 I2C数据发送过程中,发现每轮实际发送出去的数据总比在DMA配置中设定的传输数据个数要少一个。比方说:DMA配置里设定的传输数据个数是10个,结果发现在总线上只能发出9个,经过进一步发现是少了最后一个数据。…...

记录layui数据表格使用文件上传按钮
一、前言 虽然用到这种的情况不多,但是还是记录下 二、相关代码 <!DOCTYPE html> <html> <head><meta http-equiv"Content-Type" content"text/html;charsetutf-8"/><meta name"renderer" content&quo…...

c++之枚举
1、背景 在开发代码的过程中,vector类型数组a的index取了一个枚举值CTR,eg:a[CTR],刚开始以为是map类型,后面看不是,简单的看了下c的enum类型,原来enum按顺序默认为数字。 2、enum简介 2.1、…...

LeetCode 热题 100(七):105. 从前序与中序遍历序列构造二叉树、14. 二叉树展开为链表
题目一: 105. 从前序与中序遍历序列构造二叉树https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 思路:依据前序遍历的根左右和中序遍历的左根右, 且根左长度=左根 代码: …...