设计模式—职责链模式(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、六大关系

六大关系

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

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

相关文章

视频汇聚/视频云存储/视频监控管理平台EasyCVR安全检查的相关问题及解决方法

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

与面试官互动:建立积极的技术讨论氛围

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

攻击与防御实战经验分享:分析真实的攻击事件和入侵行为,讨论防御方法和实践经验

章节 1: 前言 作为IT领域的从业者&#xff0c;我们时刻都面临着网络安全的挑战。攻击者不断寻找漏洞&#xff0c;而防御者则需要时刻保持警惕&#xff0c;采取最佳实践来保护系统和数据。在本文中&#xff0c;我们将分享一些真实的攻击事件和入侵行为&#xff0c;并探讨针对这…

API 接口应该如何设计?如何保证安全?如何签名?如何防重?

说明&#xff1a;在实际的业务中&#xff0c;难免会跟第三方系统进行数据的交互与传递&#xff0c;那么如何保证数据在传输过程中的安全呢&#xff08;防窃取&#xff09;&#xff1f;除了https的协议之外&#xff0c;能不能加上通用的一套算法以及规范来保证传输的安全性呢&am…

Eclipse打jar包与JavaDOC文档的生成

补充知识点——Eclipse打jar包与JavaDOC文档的生成 1、Eclipse如何打jar包&#xff0c;如何运行jar包 Java当中编写的Java代码&#xff0c;Java类、方法、接口这些东西就是项目中相关内容&#xff0c;到时候我们需要把代码提供给甲方、或者是我们需要运行我们编写的代码&…

Docker:Harbor 私有仓库迁移

Harbor 私有仓库迁移 一.私有仓库迁移的介绍 1.为何要对Harbor 私有仓库的迁移 &#xff08;1&#xff09;硬件升级或更换&#xff1a;如果源 Harbor 在旧的硬件设备上运行&#xff0c;并且计划将其迁移到新的硬件设备上&#xff0c;那么需要执行迁移操作。 &#xff08;2&…

Python爬虫追踪新闻事件发展进程及舆论反映

目录 实现方案 1. 确定目标新闻源&#xff1a; 2. 确定关键词&#xff1a; 3. 使用网络爬虫获取新闻内容&#xff1a; 4. 提取和分析新闻文章&#xff1a; 5. 追踪新闻事件的发展进程&#xff1a; 6. 监测舆论反映&#xff1a; 7. 数据可视化&#xff1a; 完整代码示例…

ExpressLRS开源之RC链路性能测试

ExpressLRS开源之RC链路性能测试 1. 源由2. 分析3. 测试方案4. 测试设计4.1 校准测试4.2 实验室测试4.3 拉距测试4.4 遮挡测试 5. 总结6. 参考资料 1. 源由 基于ExpressLRS开源基本调试验证方法&#xff0c;对RC链路性能进行简单的性能测试。 修改设计总能够满足合理的需求&a…

香橙派OrangePi zero H2+ 驱动移远4G/5G模块

目录 1 安装系统和内核文件&#xff1a; 1.1 下载镜像 1.2 内核头安装 1.2.1 下载内核 1.2.2 将内核头文件导入开发板中 1.2.3 安装内核头 2 安装依赖工具&#xff1a; 2.1 Installing Required Host Utilities 3 驱动步骤&#xff1a; 3.1 下载模块驱动文件…

Windows上安装Hadoop 3.x

目录 0. 安装Java 1. 安装Hadoop 1.1 下载Hadoop 1.2 下载winutils 2. 配置Hadoop 1. hadoop-env.cmd 2. 创建数据目录 3. core-site.xml 4. hdfs-site.xml 3. 启动测试 3.1 namenode格式化 3.2 启动Hadoop 3.3 查看webui 3.4 测试hdfs 3.5. 测试MapReduce 4. 还…

Markdown 扩展语法练习

风无痕 August 26, 2023 Markdown 指南中文版 Markdown 入门指南Markdown 基本语法Markdown 扩展语法Markdown 基本语法练习Markdown 扩展语法练习 代码 <h3 id"table">表格</h3>| Syntax | Description | | --- | --- | | Header | Title | | Paragrap…

【Terraform学习】使用 Terraform创建 S3 存储桶事件(Terraform-AWS最佳实战学习)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…

用AI重构的钉钉,“钱”路在何方?

点击关注 文&#xff5c;郝 鑫&#xff0c;编&#xff5c;刘雨琦 钉钉2023年生态大会&#xff0c;离开了两年的无招&#xff0c;遇到了单飞9天的钉钉。 “做小钉钉、做好钉钉、做酷钉钉”&#xff0c;无招重申了钉钉的方向。 无招提到的三点&#xff0c;再加上“高质量增长”…

ubuntu22.04.1-live的vm虚拟机扩展磁盘

1、虚拟机分配硬盘100G&#xff0c;进系统df -h根目录只有50G 2、查看所有块设备 lsblk 3、 查看卷信息vgdisplay 4、在原有基础上增加49G lvextend -L 49G /dev/ubuntu-vg/ubuntu-lv 5、调整大小 resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

微信小程序 趣味学习与益智游戏系统APP

管理员、用户可通过HBuilder系统手机打开系统&#xff0c;注册登录后可进行管理员后端&#xff1b;首页、个人中心、用户管理、学生分类管理、学一学管理、玩一玩管理、听一听管理、试题管理、练一练管理、系统管理、考试管理&#xff0c;用户前端&#xff1b;首页、学一学、玩…

lenovo联想笔记本小新Air-15 2021款Intel版ITL版(82GM)原装出厂Win10系统

自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;ISO 文件大小&#xff1a;11.2GB 链接&#xff1a;https://pan.baidu.com/s/12NTMOt5eUjOIsbayXPyiww?pwdrs4v 提取码&#xf…

HTML番外篇(四)-HTML5新增元素-CSS常见函数-理解浏览器前缀-BFC

一、HTML5新增元素 1.HTML5语义化元素 在HMTL5之前&#xff0c;我们的网站分布层级通常包括哪些部分呢&#xff1f; header、nav、main、footer ◼ 但是这样做有一个弊端&#xff1a; 我们往往过多的使用div, 通过id或class来区分元素&#xff1b;对于浏览器来说这些元素不…

HCIP-OpenStack组件之neutron

neutron&#xff08;ovs、ovn&#xff09; OVS OVS(Open vSwitch)是虚拟交换机&#xff0c;遵循SDN(Software Defined Network&#xff0c;软件定义网络)架构来管理的。 OVS介绍参考&#xff1a;https://mp.weixin.qq.com/s?__bizMzAwMDQyOTcwOA&mid2247485088&idx1…

无人机航管应答机 ping200XR

产品概述 ping200XR是一个完整的系统&#xff0c;旨在满足航管应答器和自动相关监视广播(ADS-B)的要求&#xff0c;在管制空域操作无人航空系统(UAS)。该系统完全可配置为模式A&#xff0c;模式C&#xff0c;模式S转发器和扩展ADS-B发射机的任何组合。ping200XR包括一个精度超…

01 java 学习 数据类型、基础语法、封装、继承、多态、接口、泛型、异常等

目录 环境搭建和基础知识 什么是JRE: 什么是JDK: 基础数据类型 分支选择if else switch和c一毛一样 for和while循环还有数组基本和c一样 封装 函数调用、传参、命名规范、数组新命名规范 java输入Scanner scanner new Scanner(System.in); 类的创建和使用以及封装修饰符…