c#中责任链模式详解
基本介绍:
“责任链”顾名思义,是指一个需要负责处理请求的链条。
每个链条节点都是一个单独的责任者,由责任者自己决定是否处理请求或交给下一个节点。
在设计模式中的解释则为:为请求创建了一个接收者对象的链。适用于有多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定的情况。
俗话说起来就是一群领导组成了一个上下级链路关系,每个领导的职责各不相同,老百姓办事情的时候肯定没办法知道该找哪个领导。
这个时候就可以把需要办的事情交给接待人员,由接待人员自行判断是不是可以处理或者交给上级处理,至于是谁给我负责,那我这个小老百姓并不关心,只要办了就可以了。
老百姓办的事情就是请求,接待人员和领导群组成的集合就是责任链,每个领导负责自己的职责,至于最后是谁负责,那就根据具体事情一级一级的传递动态决定。
这么做的好处也显而易见,我的请求可以是任意的,具体要不要解决由谁解决,都交给责任链自己去判断。
举例说明:
公司的请假系统,当一个员工提交请假申请时,根据请假天数和职位的不同,需要由不同等级的领导审批。
项目组长》部门经理》总经理》董事长》董事会就组成了一个责任链。
普通员工和项目组长都是请假1天,但是由谁负责审批,交给责任链就可以了,由责任链自己决定由谁去审批。
比如普通员工请假1天,只需要交给项目组长审批就可以。但如果是项目组长请假1天,需要交给部门经理审批。
这种直接有单个责任人负责处理的称为纯的职责链模式,
一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理或把责任提交给上级处理。
如果普通员工请假1个月,项目组长一般没有直接审批的权限,需要先由项目组成初步审批,再由项目组长提交给部门经理进行审批。
这种单个责任人负责部分责任的情况称为不纯的职责链模式,
允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给上级的情况,且一个请求可以最终不被任何接收端对象所接收。
在一个纯的职责链模式里面,一个请求必须被某一个处理者对象所接收;
在一个不纯的职责链模式里面,一个请求可以被多个处理者对象所处理或最终不被任何接收端对象所接收。
基本结构:
抽象处理者角色:它定义一个处理请求的接口或抽象类,由于不同的具体处理者处理请求的方式不一样,因此在其中定义一个抽象的处理方法。同时该类需要维持一个指向上级的引用,通过该引用,处理者可以连成一条线。
具体处理者角色:继承自抽象类,具体实现处理方法,在处理方法中进行处理或不满足职责向上级转发请求。
客户端角色:负责链路组合顺序。
请求者角色:构建请求对象。一般通过参数方式注入到具体处理类中。
优缺点:
优点:
- 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
- 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
- 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
- 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
具体实例:
1 /// <summary>
2 /// 请假条类
3 /// </summary>
4 public class LeaveRequest
5 {
6 //请假人
7 public string Name { get; set; }
8
9 //请假天数
10 public int RestDaySum { get; set; }
11
12 //职业等级
13 public int Grade { get; set; }
14
15 //构造函数中初始化请假信息
16 public LeaveRequest(string strName, int iRestDaySum, int iGrade)
17 {
18 Name = strName;
19 RestDaySum = iRestDaySum;
20 Grade = iGrade;
21 }
22 }
23
24 /// <summary>
25 /// 抽象类
26 /// </summary>
27 public abstract class Approver
28 {
29 public Approver()
30 {
31 SetGrade();
32 }
33 //下一责任人引用
34 protected Approver _Approver;
35
36 //职业等级
37 protected int Grade { get; set; }
38
39 //设置下一个审批人,用来形成链路
40 public void SetNextApprover(Approver approver)
41 {
42 this._Approver = approver;
43 }
44
45 //设置职业等级
46 public abstract void SetGrade();
47
48 //处理请求
49 public abstract void ProcessRequest(LeaveRequest leaveRequest);
50 }
51
52 /// <summary>
53 /// 具体实现类---组长
54 /// </summary>
55 public class GroupLeader : Approver
56 {
57 public override void ProcessRequest(LeaveRequest leaveRequest)
58 {
59 if (leaveRequest.Grade >= this.Grade)
60 {
61 Console.WriteLine(leaveRequest.Name + "的请假条,组长无权处置!交由上级审核!");
62 _Approver.ProcessRequest(leaveRequest);
63 }
64 else
65 {
66 if (leaveRequest.RestDaySum > 3)
67 {
68 Console.WriteLine(leaveRequest.Name + "的请假条,请假天数超出组长的职权,交由上级审核!");
69 _Approver.ProcessRequest(leaveRequest);
70 }
71 else
72 {
73 Console.WriteLine(leaveRequest.Name + "的请假条,经由组长审核通过,批准休假。");
74 }
75 }
76 }
77
78 public override void SetGrade()
79 {
80 this.Grade = 2;
81 }
82 }
83
84 /// <summary>
85 /// 具体实现类---部门经理
86 /// </summary>
87 public class Manager : Approver
88 {
89 public override void ProcessRequest(LeaveRequest leaveRequest)
90 {
91 if (leaveRequest.Grade >= this.Grade)
92 {
93 Console.WriteLine(leaveRequest.Name + "的请假条,部门经理无权处置!交由上级审核!");
94 _Approver.ProcessRequest(leaveRequest);
95 }
96 else
97 {
98 if (leaveRequest.RestDaySum > 7)
99 {
100 Console.WriteLine(leaveRequest.Name + "的请假条,请假天数超出部门经理的职权,交由上级审核!");
101 _Approver.ProcessRequest(leaveRequest);
102 }
103 else
104 {
105 Console.WriteLine(leaveRequest.Name + "的请假条,经由部门经理审核通过,批准休假。");
106 }
107 }
108 }
109
110 public override void SetGrade()
111 {
112 this.Grade = 3;
113 }
114 }
115
116 /// <summary>
117 /// 具体实现类---总经理
118 /// </summary>
119 public class GeneralManager : Approver
120 {
121 public override void ProcessRequest(LeaveRequest leaveRequest)
122 {
123 if (leaveRequest.Grade >= this.Grade)
124 {
125 Console.WriteLine(leaveRequest.Name + "的请假条,总经理无权处置!交由上级审核!");
126 _Approver.ProcessRequest(leaveRequest);
127 }
128 else
129 {
130 if (leaveRequest.RestDaySum > 30)
131 {
132 Console.WriteLine(leaveRequest.Name + "的请假条,请假天数超出总经理的职权,交由上级审核!");
133 _Approver.ProcessRequest(leaveRequest);
134 }
135 else
136 {
137 Console.WriteLine(leaveRequest.Name + "的请假条,经由总经理审核通过,批准休假。");
138 }
139 }
140 }
141
142 public override void SetGrade()
143 {
144 this.Grade = 4;
145 }
146 }
147
148 /// <summary>
149 /// 客户端
150 /// </summary>
151 class Client
152 {
153 static void Main(string[] args)
154 {
155 //创建组长责任人
156 Approver groupLeader = new GroupLeader();
157 //创建部门经理责任人
158 Approver manager = new Manager();
159 //创建总经理责任人
160 Approver generalManager = new GeneralManager();
161
162 //设置组长的上级为部门经理
163 groupLeader.SetNextApprover(manager);
164 //设置部门经理的上级为总经理
165 manager.SetNextApprover(generalManager);
166
167 //通过以上操作构建了责任链
168
169 //创建请求---请假条---普通职员张三请假3天
170 LeaveRequest leaveRequest = new LeaveRequest("张三", 3, 1);
171 //将请假条交给责任链起始端
172 groupLeader.ProcessRequest(leaveRequest);
173 Console.WriteLine("\r\n");
174
175 //创建请求---请假条---部门经理李四请假3天
176 leaveRequest = new LeaveRequest("李四", 3, 3);
177 //将请假条交给责任链起始端
178 groupLeader.ProcessRequest(leaveRequest);
179 Console.WriteLine("\r\n");
180
181
182 //创建请求---请假条---普通职员小王请假7天
183 leaveRequest = new LeaveRequest("小王", 7, 1);
184 //将请假条交给责任链起始端
185 groupLeader.ProcessRequest(leaveRequest);
186 Console.WriteLine("\r\n");
187
188 //如果知道链条的初始端可以不用从最开始端进行
189 //创建请求---请假条---组长老刘请假3天
190 leaveRequest = new LeaveRequest("老刘", 3, 2);
191 //将请假条交给责任链中的部门经理
192 manager.ProcessRequest(leaveRequest);
193 Console.WriteLine("\r\n");
194
195 Console.ReadKey();
196 }
197 }

总结:
责任链模式属于行为型模式。它使多个对象都有机会处理请求,从而避免发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
c#中责任链模式详解的更多相关文章
- mina中责任链模式的实现
一.mina的框架回顾 责任链模式在mina中有重要的作用,其中Filter机制就是基于责任链实现的. 从上图看到消息的接受从IoService层先经过Filter层过滤处理后最后交给IoHander ...
- es6 class中责任链模式与AOP结合
责任链模式大家应该都清楚,比如JS中的冒泡,Java中的拦截器.过滤器,都运用到了责任链模式. 可以看我之前的文章介绍责任链的:https://www.cnblogs.com/wuguanglin/p ...
- Activiti工作流学习笔记(四)——工作流引擎中责任链模式的建立与应用原理
原创/朱季谦 本文需要一定责任链模式的基础,主要分成三部分讲解: 一.简单理解责任链模式概念 二.Activiti工作流里责任链模式的建立 三.Activiti工作流里责任链模式的应用 一.简单理解责 ...
- 【责任链设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
简介 责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,也叫职责链模式.命令链模式.这种模式为请求创建了一个接收者对象的链,允许你将请求沿着处理者链进行 ...
- ES6中的类继承和ES5中的继承模式详解
1.ES5中的继承模式 我们先看ES5中的继承. 既然要实现继承,首先我们得要有一个父类. Animal.prototype.eat = function(food) { console.log(th ...
- 二十:职责链模式详解(类似于spring的hangler处理请求)
定义:为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. “看这个定义,就是将一堆可以处理请求的对象连 ...
- Android中Activity启动模式详解
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...
- BarTender复合条形码中的分隔符模式详解
在BarTender 10.1中,支持使用BarTender分隔符模式的复合条形码符号体系包括GS1 Composite和GS1 DataBar (RSS).本文小编给大家详细讲解BarTender分 ...
- HTTP请求中的Keep-Alive模式详解
Keep-Alive模式 我们都知道HTTP是基于TCP的,每一个HTTP请求都需要进行三步握手.如果一个页面对某一个域名有多个请求,就会进行频繁的建立连接和断开连接.所以HTTP 1.0中出现了Co ...
- C#设计模式-责任链模式
在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1万的薪水可能技术经理就可以决定了,但是1万~1万5的薪水可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所以在面试的 ...
随机推荐
- zabbix 主动模式下报文分析
获取监控项列表 客户端发起请求 3次握手之后,请求监控项列表: {"request":"active checks","host":&quo ...
- 文件系统:ext4 的 block 分布(1G分区为例)
总的block数量:262144 $ dumpe2fs /dev/vg01/test | grep "Block count" dumpe2fs 1.42.9 (28-Dec-20 ...
- Topic太多,RocketMQ炸了!
网上博客常说,kafka的topic数量过多会影响kafka,而RocketMQ不会受到topic数量影响. 但是,果真如此吗? 最近排查一个问题,发现RocketMQ稳定性同样受到topic数量影响 ...
- Avalonia 列表拖拽替换
实现目标,在一个ListBox中选择一个子项进行拖拽到另一个ListBox中,拖拽到某一子项区域进行替换 下面是axaml代码 1 <ListBox 2 Name="consumabl ...
- Linux:通过命令查找日志文件中的某字段
工作中有用到,做个记录. 1. 查询某字段,显示行号: cat -n file_name|grep '查找字段' [root@ZWZF-CWY-LZY-12 CWY]# cat -n nohup.ou ...
- 论文解读(TAT)《 Transferable Adversarial Training: A General Approach to Adapting Deep Classifiers》
Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:Transferable Adversarial Training: A General Approach ...
- dotnet SemanticKernel 入门 自定义变量和技能
本文将告诉大家如何在 SemanticKernel 框架内定义自定义的变量和如何开发自定义的技能 本文属于 SemanticKernel 入门系列博客,更多博客内容请参阅我的 博客导航 自定义变量是一 ...
- MATLAB入门小操作(数据类型)
这是一篇有助于快速上手MATLAB软件的文章(新手向).(学习过其他的语言更容易看懂) 数据类型 这篇文章我想从MATLAB中的数据类型出发去列举一些经常使用的操作.MATLAB中的数据类型包括其他语 ...
- CodeForces-1324D-Pair-of-Topics
题意 对于两个长度为\(n\)的数组\(a[]\)和\(b[]\),找到有多少对\(i\)和\(j\)\((i<j)\),满足\(a_i+a_j>b_i+b_j\) 分析 首先发现如果\( ...
- 【项目源码】基于JavaEE的健康管理系统
随着网络技术的不断发展,网站的开发与运用变得更加广泛.这次采用java语言SSH框架(Spring,Struts,Hibernate)设计并实现了面向特定群体的健康管理平台.该网站主要有教师饮食管理. ...