本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8109100.html,记录一下学习过程以备后续查用。

一、引言

今天我们要讲行为型设计模式的第八个模式--职责链模式。让我们看看现实生活中某公司采购流程的例子吧,理解起来可能更容易。某公司的规章制度

规定,采购原材料的总价在5万之内,只需要经理级别的人批准即可;采购总价大于5万小于10万的则需要财务经理进行批准;总价大于10万小于30万的

需要总经理批准;总价大于30万的则需要通过董事会会议讨论决定。对于这样一个需求,最直接的方法就是设计一个方法,该方法接受的参数是采购的总

价,然后在这个方法内对价格进行判断,然后针对不同的条件交给不同级别的角色去处理。如果情况就是这样,不变了,这样做很好,没问题。如果我们

又有新的条件要增加该怎么办呢?我们不得不去修改原来设计的方法来再添加一个条件判断,让本已多重的if-else判断语句更多了,这样的设计显然违背

了“开闭原则”。这时候,我们可以采用职责链模式来解决这样的问题。

    二、职责链模式介绍

职责链模式:英文名称--Chain of Responsibility Pattern;分类--行为型。

2.1、动机(Motivate)

在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者

的紧耦合。如何使请求的发送者不需要指定具体的接受者,让请求的接受者自己在运行时决定来处理请求,从而使两者解耦。

2.2、意图(Intent)

避免请求发送者与接收者耦合在一起,让多个对象都有可能接受请求,将这些对象连接成一条链,并且沿着这条链传递请求,知道有对象处理它为止。

——《设计模式》GoF

2.3、结构图(Structure)

2.4、模式的组成

可以看出,在职责链模式的结构图有以下角色:

1)抽象处理者角色(Handler):抽象处理者定义了一个处理请求的接口,它一般设计为抽象类。由于不同的具体处理者处理请求的方式不同,因此在

其中定义了抽象请求处理方法。因为每一个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个自类型的对象,作为其对下家的引用。通过该

引用,处理者可以连成一条链。

2)具体处理者角色(ConcreteHandler):具体处理者是抽象处理者的子类,它可以处理用户请求。在具体处理者类中实现了抽象处理者中定义的抽象

处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限?如果可以处理请求就处理它,否则将请求转发给后继者。在具体处理者中可以访问

链中下一个对象,以便请求的转发。

2.5、职责链模式的具体实现

在现实生活中,职责链模式的例子也是很多的,例如:公司的请假流程就是一个很好的职责链模式的例子。如果请假半天,只要告诉本部门经理就可以

了;如果请假7天或者以上必须人事总监批准;如果请假15天以上,那就要经过总裁批准了。还有类似的例子就是采购的流程,其流程也是职责链模式很

好的体现,采购金额的不同,需要批准的人员也不同。下面就以采购的实例来说明职责链模式,实现代码如下:

    class Program{/// <summary>/// 采购请求/// </summary>public sealed class PurchaseRequest{//金额public double Amount { get; set; }//产品名字public string ProductName { get; set; }public PurchaseRequest(double amount, string productName){Amount = amount;ProductName = productName;}}/// <summary>/// 抽象审批人--相当于“抽象处理者角色”/// </summary>public abstract class Approver{//下一位审批人,由此形成一条链。public Approver NextApprover { get; set; }//审批人的名称public string Name { get; set; }public Approver(string name){Name = name;}//处理请求public abstract void ProcessRequest(PurchaseRequest request);}/// <summary>/// 部门经理--相当于“具体处理者角色”/// </summary>public sealed class Manager : Approver{public Manager(string name) : base(name) { }public override void ProcessRequest(PurchaseRequest request){if (request.Amount <= 10000.0){Console.WriteLine("部门经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);}else if (NextApprover != null){Console.WriteLine("部门经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);NextApprover.ProcessRequest(request);}}}/// <summary>/// 财务经理--相当于“具体处理者角色”/// </summary>public sealed class FinancialManager : Approver{public FinancialManager(string name) : base(name) { }public override void ProcessRequest(PurchaseRequest request){if (request.Amount > 10000.0 && request.Amount <= 50000.0){Console.WriteLine("财务经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);}else if (NextApprover != null){Console.WriteLine("财务经理{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);NextApprover.ProcessRequest(request);}}}/// <summary>/// 总裁--相当于“具体处理者角色”/// </summary>public sealed class CEO : Approver{public CEO(string name) : base(name) { }public override void ProcessRequest(PurchaseRequest request){if (request.Amount > 50000.0 && request.Amount < 300000.0){Console.WriteLine("总裁{0}批准了对原材料{1}的采购计划。", Name, request.ProductName);}else{Console.WriteLine("这个采购计划的金额比较大,需要董事会会议讨论才能决定。");}}}static void Main(string[] args){#region 职责链模式PurchaseRequest requestDao = new PurchaseRequest(9000.0, "单刀5把");PurchaseRequest requestHuaJi = new PurchaseRequest(40000.0, "10把方天画戟");PurchaseRequest requestJian = new PurchaseRequest(90000.0, "5把金丝龙鳞闪电劈");Approver manager = new Manager("黄飞鸿");Approver financial = new FinancialManager("黄麒英");Approver ceo = new CEO("十三姨");//设置职责链manager.NextApprover = financial;financial.NextApprover = ceo;//处理请求
            manager.ProcessRequest(requestDao);Console.WriteLine();manager.ProcessRequest(requestHuaJi);Console.WriteLine();manager.ProcessRequest(requestJian);Console.ReadLine();#endregion}}

View Code

运行结果如下:

三、职责链模式的实现要点

Chain of Responsibility模式的应用场合在于“一个请求可能有多个接受者,但是最后真正的接受者只有一个”,只有这时候请求发送者与接受者的耦合才

有可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好地应对变化。

应用了Chain of Responsibility模式后,对象的职责分派将更具灵活性,我们可以在运行时动态添加/修改请求的处理职责。

当我们要新增一个Handler处理请求,就不需再改原来的代码了,遵从了开放封闭原则。这样我们的程序就更赋予变化,更有变化的抵抗力。Handler类

本身继承自BaseHandler类型,又包含了一个BaseHandler类型的对象,这点类似Decorator模式。

如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制,这也是每一个接受对象的责任,而不是发出请求的对象的责任。

3.1、职责链模式的主要优点

1)降低耦合度:职责链模式使得一个对象无需知道是其它哪一个对象处理其请求,对象仅需知道该请求会被处理即可。接受者和发送者都没有对方的明

确信息,且链中的对象不需要知道链的结构,有客户端负责链的创建。

2)可简化对象的相互连接:接受者对象仅需维持一个指向其后继者的引用,而不需维持它对所有的候选处理者的引用。

3)增强给对象指派职责的灵活性:在给对象分派职责时,职责链可以给我们带来更多的灵活性。可以通过在运行时对该连进行动态的增加或修改处理一

个请求的职责。

4)增加新的请求处理类很方便:在系统中增加一个新的请求处理者无需修改原有系统的代码,只需要在客户端重新建链即可,从这一点看来是符合开闭

原则的。

 3.2、职责链模式的主要缺点

1)在找到正确的处理对象之前,所有的条件判定都要执行一遍,当责任链过长时,可能会引起性能的问题。

2)可能导致某个请求不被处理。

3)客户端需要组装这个链条,耦合了客户端和链条的组成结构,可以把这个在客户端的组合动作提到外面,通过配置来做会更好点。

3.3、在下面的情况下可以考虑使用职责链模式

1)一个系统的审批需要多个对象才能完成处理的情况下,例如请假系统等。

2)代码中存在多个if-else语句的情况下,此时可以考虑使用责任链模式来对代码进行重构。

3)有多个对象可以处理同一个请求,具体哪个对象处理该请求在运行时刻自动确定。客户端只需将请求提交到链上,无须关心请求的处理对象是谁以及

它是如何处理的。

4)不明确指定接受者的情况下,向多个对象中的一个提交一个请求。请求的发送者与请求者解耦,请求将沿着链进行传递,寻求响应的处理者。

5)可动态指定一组对象处理请求。客户端可以动态创建职责链来处理请求,还可以动态改变链中处理者之间的先后次序。

    四、.NET中职责链模式的实现

这个模式在.Net框架中的实现不多,个人觉得这个模式的使用场景更多的是在业务系统中才会有更大的用处。这种模式在处理UI的消息时很常用,但实际

上Windows消息循环还是硬编码的结构,主要是效率上的考虑。Windows消息循环是哪个对象有一个请求,则直接将请求送至处理函数的地址。如果链条上

的对象多了,而真正处理的函数在链条后部分,效率会很低下。因此我们在使用这种模式的时候更适合业务流程,即对性能要求不是特别高的情况更加常用。

    五、总结

这个模式也是为了解耦,解耦请求的发送者和接受者,当有新的需求的时候更容易变化,让我们的代码更符合面向对象OO的设计。

C#设计模式学习笔记:(20)职责链模式相关推荐

  1. atitit.设计模式(1)--—职责链模式(chain of responsibility)最佳实践O7 日期转换

    atitit.设计模式(1)---职责链模式(chain of responsibility)最佳实践O7 日期转换 1. 需求:::日期转换 1 2. 可以选择的模式: 表格模式,责任链模式 1 3 ...

  2. 设计模式学习笔记——享元(Flyweight)模式

    设计模式学习笔记--享元(Flyweight)模式 @(设计模式)[设计模式, 享元模式, flyweight] 设计模式学习笔记享元Flyweight模式 基本介绍 享元案例 类图 实现代码 Big ...

  3. 设计模式学习笔记——中介者(Mediator)模式

    设计模式学习笔记--中介者(Mediator)模式 @(设计模式)[设计模式, 中介者模式, Mediator] 设计模式学习笔记中介者Mediator模式 基本介绍 中介者案例 类图 实现代码 Me ...

  4. 设计模式学习笔记——单例(Singleton)模式

    设计模式学习笔记--单例(Singleton)模式 @(设计模式)[设计模式, 单例模式, Singleton, 懒汉式, 饿汉式] 设计模式学习笔记单例Singleton模式 基本介绍 单例案例 类 ...

  5. C#设计模式之二十职责链模式(Chain of Responsibility Pattern)【行为型】

    一.引言 今天我们开始讲"行为型"设计模式的第八个模式,该模式是[职责链模式],英文名称是:Chain of Responsibility Pattern.让我们看看现实生活中的例 ...

  6. 设计模式的理解: 职责链模式 (Chain of Responsibility)

    职责链模式(Chain of Responsibility Pattern),为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为型模式. ...

  7. 重温设计模式(三)——职责链模式(chain of responsibility)

    一. 写在前面的 这么多的设计模式,我觉得职责链是我第一次看上去最简单,可是回想起来却又最复杂的一个模式. 因此,这个文章我酝酿了很久,一直也没有胆量发出来,例子也是改了又改,可是仍然觉得不够合理.所 ...

  8. 设计模式学习笔记--Mediator 中介者模式

    我们知道面向对象应用程序是由一组为了提供某种服务而彼此交互的对象组成.当彼此引用的对象数量比较少时,此时对象之间就为直接交互(点对点).而当对象的数量增加时,这种直接交互会导致对象之间复杂的.混乱的引 ...

  9. 设计模式学习笔记--Flyweight享元模式

    Flyweight模式也叫享元模式,是由GoF提出的23种设计模式中的一种.Flyweight模式是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用,所以叫享元.   此模式解决的是由于大量 ...

最新文章

  1. 笔记JavaScript基本概念
  2. 数据库持久 项目重启_Aerospike + ScaleFlux 提供的超高性能方案助力同盾超大规模核心数据库系统...
  3. 最小二乘法与最大似然函数的区别
  4. [云炬python3玩转机器学习笔记] 2-1机器学习基础概念
  5. k8s StatefulSet
  6. System类的常用方法及类字段
  7. Common Number(奇偶二分+找规律)
  8. vsftpd的主配置文件是什么linux,vsftpd.conf配置文件详解
  9. 【Linux入门学习之】ubuntu10.04 ruijie配置上网(用mentohust)
  10. arm linux vlc移值,vlc-3.0.8在飞凌开发板i.mx6q上移植
  11. python给函数设置超时时间已到_在 Linux/Mac 下为Python函数添加超时时间
  12. 【工程/物理光学(一)——光的电磁理论基础】
  13. ds6708 symbol 驱动_Symbol DS6708条码扫描器
  14. linux查看虚拟内存使用,Linux 使用 vmstat 查看虚拟内存状态
  15. xp启用计算机共享打印机,Win7共享XP打印机设置方法【win7不能共享xp打印机】解决方法...
  16. 七月流火,让我们共享一场开源数据库的饕餮盛宴
  17. Java实现航空机票订票系统
  18. GTX1650Super和GTX1060哪个好?
  19. NLP 学习教程 第一节 简介
  20. APC型光纤活动连接器有何特点?适合使用在什么场景?

热门文章

  1. Shell编程:简洁的 Bash Programming 技巧续篇
  2. 防止电子邮件地址被搜索到的新方法
  3. UITabBarController 标签栏控制器-IOS开发 (实例)
  4. 并查集——畅通工程(hdu1232)
  5. Samba配置文件解析
  6. 02 李俊杰 20160221-S1笔试
  7. 构造方法重载 java 1615136407
  8. django-模态框添加学生
  9. 动态规划的理解与案例分析
  10. 张家口市12320卫生热线呼叫中心预计今年初启动