23种设计模式之责任链模式(Chain of Responsibility Pattern)
责任链模式(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)的更多相关文章
- 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)
责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...
- 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)
原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...
- 23种设计模式之责任链模式(Chain of Responsibility)
责任链模式是一种对象的行为型模式,避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止.责任链模式不保证每个请求都被接受, ...
- 【Unity与23种设计模式】责任链模式(Chain of Responsibility)
GoF中定义: "让一群对象都有机会来处理一项请求,以减少请求发送者与接收者之间的耦合度.将所有的接受对象串联起来,让请求沿着串接传递,直到有一个对象可以处理为止." 举个现实中的 ...
- 23种设计模式--责任链模式-Chain of Responsibility Pattern
一.责任链模式的介绍 责任链模式用简单点的话来说,将责任一步一步传下去,这就是责任,想到这个我们可以相当击鼓传花,这个是为了方便记忆,另外就是我们在项目中经常用到的审批流程等这一类的场景时我们就可以考 ...
- C#设计模式-责任链模式(Chain of Responsibility Pattern)
引子 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程,软件开发中的异常处理流程,web请求处理流程等各种各样的流程,可以考虑使用责任链模式来实现.现在以请假流程为例,一般公 ...
- [设计模式] 13 责任链模式 Chain of Responsibility
转 http://blog.csdn.net/wuzhekai1985 http://www.jellythink.com/archives/878 向项目经理提交了休假申请,我的项目经理向 ...
- 设计模式 笔记 责任链模式 chain of responsibility
//---------------------------15/04/25---------------------------- //Chain of responsibility 责任链----- ...
- 责任链模式 职责链模式 Chain of Responsibility Pattern 行为型 设计模式(十七)
责任链模式(Chain of Responsibility Pattern) 职责链模式 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系 将这些对象连接成一条链,并沿着这 ...
随机推荐
- Mybatis关联查询<association> 和 <collection>
一.背景 1.在系统中一个用户存在多个角色,那么如何在查询用户的信息时同时把他的角色信息查询出来啦? 2.用户pojo: public class SysUser { private Long id; ...
- GRE Words Revenge AC自动机 二进制分组
GRE Words Revenge 题意和思路都和上一篇差不多. 有一个区别就是需要移动字符串.关于这个字符串,可以用3次reverse来转换, 前面部分翻转一下, 后面部分翻转一下, 最后整个串翻转 ...
- 用深度学习技术FCN自动生成口红
1 这个是什么? 基于全卷积神经网络(FCN)的自动生成口红Python程序. 图1 FCN生成口红的效果(注:此两张人脸图来自人脸公开数据库LFW) 2 怎么使用了? 首 ...
- 网络流---最大流(Edmond-Karp算法)的学习
先上个代码,等有空补充详解 #include<iostream> #include<cstdio> #include<cstring> #include<cm ...
- super(classname,self).__init__() 作用
- Java面试-动态规划与组合数
最近在刷力扣上的题目,刷到了65不同路径,当初上大学的时候,曾在hihocoder上刷到过这道题目,但是现在已经几乎全忘光了,大概的知识点是动态规划,如今就让我们一起来回顾一下. 从题目说起 题目原文 ...
- protobuf初识
protobuf是一种高效的数据格式,平台无关.语言无关.可扩展,可用于 RPC 系统和持续数据存储系统. protobuf protobuf介绍 Protobuf是Protocol Buffer的简 ...
- Linux中新建用户用不了sudo命令问题:rootr is not in the sudoers file.This incident will be reported解决
参考:https://blog.csdn.net/lichangzai/article/details/39501025 如果执行sudo命令的用户没有执行sudo的权限,执行sudo命令时会报下面的 ...
- 服务器替换san存储
1.通知DBA停库: 串行登陆服务器 2.备份系统信息 mkdir -p /bakinfo df -h > /bakinfo/df.txt_`date +%Y%m%d%H%M%S` ps -ef ...
- win7右下角声音图标不见了
场景:开机后发生右下角的声音图标不见了,马上google,可能性有两种图标隐藏或者系统错误 隐藏处理方式:右下角下打开自定义--> 将它调为显示和通知(发生不好使,估计是系统错误) 系统错误处理 ...