基本介绍:

  “责任链”顾名思义,是指一个需要负责处理请求的链条

  每个链条节点都是一个单独的责任者,由责任者自己决定是否处理请求或交给下一个节点

  在设计模式中的解释则为:为请求创建了一个接收者对象的链。适用于有多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定的情况。

  俗话说起来就是一群领导组成了一个上下级链路关系,每个领导的职责各不相同,老百姓办事情的时候肯定没办法知道该找哪个领导。

  这个时候就可以把需要办的事情交给接待人员,由接待人员自行判断是不是可以处理或者交给上级处理,至于是谁给我负责,那我这个小老百姓并不关心,只要办了就可以了。

  老百姓办的事情就是请求,接待人员和领导群组成的集合就是责任链,每个领导负责自己的职责,至于最后是谁负责,那就根据具体事情一级一级的传递动态决定。

  这么做的好处也显而易见,我的请求可以是任意的,具体要不要解决由谁解决,都交给责任链自己去判断。

举例说明:

  公司的请假系统,当一个员工提交请假申请时,根据请假天数和职位的不同,需要由不同等级的领导审批。

  项目组长》部门经理》总经理》董事长》董事会就组成了一个责任链。

  普通员工和项目组长都是请假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#中责任链模式详解的更多相关文章

  1. mina中责任链模式的实现

    一.mina的框架回顾 责任链模式在mina中有重要的作用,其中Filter机制就是基于责任链实现的. 从上图看到消息的接受从IoService层先经过Filter层过滤处理后最后交给IoHander ...

  2. es6 class中责任链模式与AOP结合

    责任链模式大家应该都清楚,比如JS中的冒泡,Java中的拦截器.过滤器,都运用到了责任链模式. 可以看我之前的文章介绍责任链的:https://www.cnblogs.com/wuguanglin/p ...

  3. Activiti工作流学习笔记(四)——工作流引擎中责任链模式的建立与应用原理

    原创/朱季谦 本文需要一定责任链模式的基础,主要分成三部分讲解: 一.简单理解责任链模式概念 二.Activiti工作流里责任链模式的建立 三.Activiti工作流里责任链模式的应用 一.简单理解责 ...

  4. 【责任链设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

    简介 责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,也叫职责链模式.命令链模式.这种模式为请求创建了一个接收者对象的链,允许你将请求沿着处理者链进行 ...

  5. ES6中的类继承和ES5中的继承模式详解

    1.ES5中的继承模式 我们先看ES5中的继承. 既然要实现继承,首先我们得要有一个父类. Animal.prototype.eat = function(food) { console.log(th ...

  6. 二十:职责链模式详解(类似于spring的hangler处理请求)

    定义:为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. “看这个定义,就是将一堆可以处理请求的对象连 ...

  7. Android中Activity启动模式详解

    在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...

  8. BarTender复合条形码中的分隔符模式详解

    在BarTender 10.1中,支持使用BarTender分隔符模式的复合条形码符号体系包括GS1 Composite和GS1 DataBar (RSS).本文小编给大家详细讲解BarTender分 ...

  9. HTTP请求中的Keep-Alive模式详解

    Keep-Alive模式 我们都知道HTTP是基于TCP的,每一个HTTP请求都需要进行三步握手.如果一个页面对某一个域名有多个请求,就会进行频繁的建立连接和断开连接.所以HTTP 1.0中出现了Co ...

  10. C#设计模式-责任链模式

    在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1万的薪水可能技术经理就可以决定了,但是1万~1万5的薪水可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所以在面试的 ...

随机推荐

  1. EaselJS 源码分析系列--第四篇

    鼠标交互事件 前几篇关注的是如何渲染,那么鼠标交互如何实现呢? Canvas context 本身没有像浏览器 DOM 一样的交互事件 EaselJS 如何在 canvas 内实现自己的鼠标事件系统? ...

  2. 我用WebGL打造了一款动态壁纸

    我用WebGL打造了一款动态壁纸 简述 最近在给自己电脑换壁纸的时候发现了一张很有特点的图(就是下面这张),于是我突发奇想,要是能把这张图变成一张动态的壁纸.那该多好.于是我打算用threejs开发一 ...

  3. Vue项目打包后放到SpringBoot项目里注意点

  4. PE文件结构2(实现PE文件载入)

    现在我们已经学完了PE文件格式,但是尚还停留在纸上谈兵的阶段,作为Windows系统上的可执行文件格式,PE文件结构总是和结构体,指针等紧密联系在一起的.理解它的最好方法就是通过写一个类似LordPE ...

  5. [ABC149E] Handshake

    2023-03-06 题目 题目传送门 翻译 翻译 难度&重要性(1~10):4 题目来源 AtCoder 题目算法 二分 解题思路 因为按照贡献从大到小握手一定是最优的,所以将 \(a\) ...

  6. 《Kali渗透基础》09. 漏洞利用、后渗透

    @ 目录 1:漏洞基本介绍 1.1:漏洞从哪里来 1.2:缓冲区溢出 1.3:如何发现漏洞 2:漏洞利用 2.1:EXP 选择与修改 2.2:避免有害的 EXP 3:后渗透阶段 3.1:Linux 上 ...

  7. 商品详情api接口的应用方向有哪些?

    ​ 商品详情API接口的应用方向非常广泛,可以应用于以下领域: 电子商务平台:商品详情API接口可以提供商品的基本信息,如名称.描述.价格.图片等,帮助电子商务平台展示和推荐商品.此外,还可以提供商品 ...

  8. 关于Unity 如何与Blazor Server结合

    关于Unity 如何与Blazor Server结合 一.介绍 最近工作中有`Unity`与`Blazor Server`结合的需求,在网上找了一圈,发现这方面的资料比较少,特此写下这篇记录一下自己的 ...

  9. Solution -「洛谷 P4451」「国家集训队」整数的 lqp 拆分

    Description Link. 求 \[\sum\prod_{i=1}^{m}F_{a_{i}},(m>0,a_{1},\cdots a_{m}>0,\sum a_{i}=n) \] ...

  10. Oracle-判断表上存在高水位线

    表上高水位线:通常一个新建的表,1个8K的数据块存放100行记录,若表上经常插入删除操作,造成表的水位线很高.下面从发现高水位线的办法,及解决高水位的方法说起: 1.发现存在高水位线的表:查看字典表u ...