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

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了

优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。

缺点: 1、不能保证请求一定被接收。 2、在找到正确的处理对象之前,所有的条件判定都要执行一遍,当责任链过长时,可能会引起性能的问题。 3、可能不容易观察运行时的特征,有碍于除错。

应用实例: 1、JS 中的事件冒泡。2、在现实生活中,有很多请求并不是一个人说了就算的,例如面试时的工资,低于1万的薪水可能技术经理就可以决定了,但是1万~1万5的薪水可能技术经理就没这个权利批准,可能就需要请求技术总监的批准,所以在面试的完后,经常会有面试官说,你这个薪水我这边觉得你这技术可以拿这个薪水的,但是还需要技术总监的批准等的话。

主要涉及两个角色

  • 抽象处理者角色(Handler):定义出一个处理请求的接口。这个接口通常由接口或抽象类来实现。
  • 具体处理者角色(ConcreteHandler):具体处理者接受到请求后,可以选择将该请求处理掉,或者将请求传给下一个处理者。因此,每个具体处理者需要保存下一个处理者的引用,以便把请求传递下去

实现代码:

     public abstract class AbstractAuditor
{
public string Name { get; set; }
public abstract void Audit(ApplyContext context); private AbstractAuditor _NextAuditor = null;
public void SetNext(AbstractAuditor auditor)
{
this._NextAuditor = auditor;
}
protected void AuditNext(ApplyContext context)
{
if (this._NextAuditor != null)
{
this._NextAuditor.Audit(context);
}
else
{
context.AuditResult = false;
context.AuditRemark = "不允许请假!";
}
}
}
     /// <summary>
/// 请假申请,
/// Context--上下文环境,保存业务处理中参数-中间结果-最终结果
/// 行为型设计模式常用的标配
/// 把行为转移,
/// </summary>
public class ApplyContext
{
public int Id { get; set; }
public string Name { get; set; }
/// <summary>
/// 请假时长
/// </summary>
public int Hour { get; set; }
public string Description { get; set; }
public bool AuditResult { get; set; }
public string AuditRemark { get; set; }
}
     /// <summary>
/// 职责问题:
/// 1 权限范围内,审批通过
/// 2 权限范围外,交给下一环节审批
/// 写的代码又多了一个,指定下一环节
/// 甩锅大法
/// </summary>
public class PM : AbstractAuditor
{
public override void Audit(ApplyContext context)
{
Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
if (context.Hour <= )
{
context.AuditResult = true;
context.AuditRemark = "允许请假!";
}
else
{
base.AuditNext(context);
}
}
}
     public class Charge: AbstractAuditor
{
public override void Audit(ApplyContext context)
{
Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
if (context.Hour <= )
{
context.AuditResult = true;
context.AuditRemark = "允许请假!";
}
else
{
base.AuditNext(context);
}
}
}
     public class Manager : AbstractAuditor
{
public override void Audit(ApplyContext context)
{
Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
if (context.Hour <= )
{
context.AuditResult = true;
context.AuditRemark = "允许请假!";
}
else
{
base.AuditNext(context);
}
}
}
     public class Chief : AbstractAuditor
{
public override void Audit(ApplyContext context)
{
Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
if (context.Hour <= )
{
context.AuditResult = true;
context.AuditRemark = "允许请假!";
}
else
{
base.AuditNext(context);
//....
}
}
}
     public class CEO : AbstractAuditor
{
public override void Audit(ApplyContext context)
{
Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
if (context.Hour <= )
{
context.AuditResult = true;
context.AuditRemark = "允许请假!";
}
else
{
base.AuditNext(context);
//....
}
}
}
     public class ChiarMan : AbstractAuditor
{
public override void Audit(ApplyContext context)
{
Console.WriteLine($"This is {this.GetType().Name} {this.Name} Audit");
if (context.Hour <= )
{
context.AuditResult = true;
context.AuditRemark = "允许请假!";
}
else
{
base.AuditNext(context);
//....
}
}
}

前端调用:

                 ApplyContext context = new ApplyContext()
{
Id = ,
Name = "aaa",
Hour = ,
Description = "我想...",
AuditResult = false,
AuditRemark = ""
};
//流程的可扩展 AbstractAuditor auditor = AuditorBuilder.Build();
auditor.Audit(context);
if (!context.AuditResult)
{
Console.WriteLine("不干了!");
}
//把流程环节逻辑从业务类转移了
     public class AuditorBuilder
{
/// <summary>
/// 那就反射+配置文件
/// 链子的组成都可以通过配置文件
/// </summary>
/// <returns></returns>
public static AbstractAuditor Build()
{
AbstractAuditor pm = new PM()
{
Name = "bbb"
};
AbstractAuditor charge = new Charge()
{
Name = "ccc"
};
AbstractAuditor manager = new Manager()
{
Name = "ddd"
};
AbstractAuditor chief = new Chief()
{
Name = "eee"
};
AbstractAuditor ceo = new CEO()
{
Name = "fff"
}; pm.SetNext(charge);
charge.SetNext(manager);
//pm.SetNext(manager);
manager.SetNext(chief);
chief.SetNext(ceo);
ceo.SetNext(new ChiarMan()
{
Name = "ggg"
});
return pm;
}
}

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

本文参考文档:

https://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html

https://www.cnblogs.com/zhili/p/ChainOfResponsibity.html

https://www.cnblogs.com/abcdwxc/archive/2007/09/25/905622.html

23种设计模式之责任链模式(Chain of Responsibility Pattern)的更多相关文章

  1. 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)

    责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...

  2. 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)

    原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...

  3. 23种设计模式之责任链模式(Chain of Responsibility)

    责任链模式是一种对象的行为型模式,避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止.责任链模式不保证每个请求都被接受, ...

  4. 【Unity与23种设计模式】责任链模式(Chain of Responsibility)

    GoF中定义: "让一群对象都有机会来处理一项请求,以减少请求发送者与接收者之间的耦合度.将所有的接受对象串联起来,让请求沿着串接传递,直到有一个对象可以处理为止." 举个现实中的 ...

  5. 23种设计模式--责任链模式-Chain of Responsibility Pattern

    一.责任链模式的介绍 责任链模式用简单点的话来说,将责任一步一步传下去,这就是责任,想到这个我们可以相当击鼓传花,这个是为了方便记忆,另外就是我们在项目中经常用到的审批流程等这一类的场景时我们就可以考 ...

  6. C#设计模式-责任链模式(Chain of Responsibility Pattern)

    引子 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现.现在以请假流程为例,一般公 ...

  7. [设计模式] 13 责任链模式 Chain of Responsibility

    转    http://blog.csdn.net/wuzhekai1985   http://www.jellythink.com/archives/878 向项目经理提交了休假申请,我的项目经理向 ...

  8. 设计模式 笔记 责任链模式 chain of responsibility

    //---------------------------15/04/25---------------------------- //Chain of responsibility 责任链----- ...

  9. 责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)

    责任链模式(Chain of Responsibility Pattern) 职责链模式 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系 将这些对象连接成一条链,并沿着这 ...

随机推荐

  1. Hugo

    快速开始 安装Hugo 1.二进制安装(推荐:简单.快速) 到 Hugo Releases 下载对应的操作系统版本的Hugo二进制文件(hugo或者hugo.exe) Mac下直接使用 ==Homeb ...

  2. MSIL实用指南-位运算

    C#支持的位运算是与.或.异或.取反.左移.右移,它们对应的指令是And.Or.Xor.Not.Shl.Shr. 取反运算只需要一个操作数,生成步骤是1.生成加载变量2.生成取反指令实例代码: ilG ...

  3. Oracle批量更改所有表的字段取值_类型_原字段名

    CREATE PROCEDURE 存储过程名称 is cursor c_tab is select * from user_tab_columns t r_tab user_tab_columns%r ...

  4. mongodb 启动 WARNING: soft rlimits too low, transparent_hugepage/enabled is 'always'. never

    今天启动mongodb的时候,之前一直没注意,今天发现又warning,想整一整. 下面是告警 2019-09-05T12:00:55.271+0800 I CONTROL [initandliste ...

  5. HZNU Training 4 for Zhejiang Provincial Collegiate Programming Contest 2019

    今日这场比赛我们准备的题比较全面,二分+数论+最短路+计算几何+dp+思维+签到题等.有较难的防AK题,也有简单的签到题.为大家准备了一份题解和AC代码. A - Meeting with Alien ...

  6. yzoj1891 最优配对问题 题解

    题意 有n个点,且2|n,要求将其分为n/2对点对使得所有点对中距离之和尽量小 输出保留两位小数 考虑数据范围先想到的是搜索,然而搜索超时,我们发现在搜索的时候有重复搜索的情况,那么考虑记忆化,看到数 ...

  7. buuctf 随便注 writeup

    1.0 打开页面 显然这个题的考点是注入,那我们来测一下 2.0 sql注入测试 1 2 输入 1' 后发现没有回显,改为 1' --+ 后,有回显,应该在这存在注入点 试一下 1' and 1=1 ...

  8. Django系列---使用MySql数据库

    目录 1. 创建数据库 1.1. 使用utf8mb4编码 1.1.1. 确定mysql的配置文件 1.1.2. 修改配置文件 1.1.3. 重启数据库服务,检查相关字段 1.1.4. 新建数据库 1. ...

  9. 【LeetCode】[0002] 【两数之和】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 给出两个非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字.如果 ...

  10. 初玩Docker

    Docker 和VM的区别 Docker就是类似于一个打包好的环境,相关的服务都安装在里面,可以直接使用的. VM就相当于另外一套独立的系统,独立的IP,虚拟硬件. 要使用就需要单独构建一套才可以. ...