目录

一、概念

二、责任链模式案例

三、总结


一、概念

责任链模式的定义如下:

多个请求接收者串成一条链式结构,一个请求到达请求链上,如果该接收者不能处理请求则会将请求继续往下传递(通常每个接收者都包含对另一个接收者的引用),以此类推,直到找到有一个请求接收者能够处理该请求。职责链模式将请求发送者和请求接收者进行了解耦,此种模式属于行为型模式。

责任链模式的重点是在"链"上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果,其通用类图如下:

角色分析:

  • IRequestHandler:抽象处理者角色,可以是接口或者抽象类,里面聚合了抽象处理者本身,定义了具体请求处理者处理请求的方法以及获取、设置下一个请求处理者的方法;
  • ConcreateRequestHandler:具体请求接收者角色,实现了抽象请求接收者中定义的抽象方法,接收到请求后,如果可以处理该请求就处理,如果不能处理就交给请求调用链中下一个请求接收者进行处理;
  • Client:客户端,是请求发送的对象;

二、责任链模式案例

考虑以下这样的场景:

你在公司需要请假,当你请假一天的时候,这时候自己的直接主管就能完成审批;如果请假超过一天但小于三天的时候,这时候直接主管就不能审批了,此时需要交给部门主管才能审批,同样的,当请假天数超过三天时,部门主管也不能审批了,此时需要交给总经理进行审批。

类似这种流程审批的场景,在工作中比较常见,此时责任链模式将非常适合这种场景。

类图如下:

首先我们需要定义个请假请求对象:

/*** 请求请求*/
public class Request {/*** 请假人姓名*/private String name;/*** 请假天数*/private int day;public Request(String name, int days) {this.name = name;this.day = days;System.out.println(name + "发起申请,需要请假" + days + "天");}public int getDay() {return day;}public String getName() {return name;}
}

接下来就需要定义一个抽象的处理者对象:

/*** 抽象处理器*/
public abstract class AbstractHandler {/*** 下一个处理节点*/private AbstractHandler nextHandler = null;/*** 记录每种角色能够审批的最大请假天数** @return*/public abstract int getLimit();/*** 每种角色名称*/public abstract String getHandlerName();public void setNextHandler(AbstractHandler nextHandler) {this.nextHandler = nextHandler;}/*** 具体执行方法** @param request*/public final void handle(Request request) {if (getLimit() >= request.getDay()) {System.out.println(getHandlerName() + "审批请假请求");} else {if (this.nextHandler != null) {//交给链中的下一个处理器进行处理this.nextHandler.handle(request);} else {System.out.println("请假天数太长,无法审批");}}}}

抽象处理者主要包含了一个自身的引用、设置下一个处理者对象的方法、以及具体执行方法:

/*** 抽象处理器*/
public abstract class AbstractHandler {/*** 下一个处理节点*/private AbstractHandler nextHandler = null;/*** 记录每种角色能够审批的最大请假天数** @return*/public abstract int getLimit();/*** 每种角色名称*/public abstract String getHandlerName();public void setNextHandler(AbstractHandler nextHandler) {this.nextHandler = nextHandler;}/*** 具体执行方法** @param request*/public final void handle(Request request) {if (getLimit() >= request.getDay()) {System.out.println(getHandlerName() + "审批请假请求");} else {if (this.nextHandler != null) {//交给链中的下一个处理器进行处理this.nextHandler.handle(request);} else {System.out.println("请假天数太长,无法审批");}}}}

有了抽象处理者,下面就需要定义几个具体的请求处理者,在此例中,就是直接主管审批、部门经理审批、总经理审批这几个处理者,以便可以组成一条链:

public class DirectLeaderHandler extends AbstractHandler {@Overridepublic String getHandlerName() {return "直接主管";}@Overridepublic int getLimit() {return 1;}}public class DeptManagerHandler extends AbstractHandler {@Overridepublic String getHandlerName() {return "部门经理";}@Overridepublic int getLimit() {return 3;}
}public class ManagerHandler extends AbstractHandler {@Overridepublic String getHandlerName() {return "总经理";}@Overridepublic int getLimit() {return 30;}
}

下面我们定义一个场景类:

/*** 场景类*/
public class Client {public static void main(String[] args) {AbstractHandler employee = new DirectLeaderHandler();AbstractHandler leader = new DeptManagerHandler();AbstractHandler manager = new ManagerHandler();//将链串起来employee.setNextHandler(leader);leader.setNextHandler(manager);employee.handle(new Request("张三", 5));System.out.println("===================");employee.handle(new Request("李四", 2));System.out.println("===================");employee.handle(new Request("王五", 50));}
}

运行结果:

张三发起申请,需要请假5天
总经理审批请假请求
===================
李四发起申请,需要请假2天
部门经理审批请假请求
===================
王五发起申请,需要请假50天
请假天数太长,无法审批

可见,根据不同的请求,将会找到不同的具体请求接收者去处理,如果当前接收者不能处理,则继续往下找下一个能处理请求的接收者,如果到最后都找不到,则抛出不能处理异常或者直接返回,这就是职责链模式。

在实际应用中,一般会有一个封装类堆责任链模式进行封装,也就是替代Client场景类,直接返回链中的第一个处理者,具体链的设置不需要高层次模块关系,这样,更简化了高层次模块的调用,减少模块间的耦合,提高系统的灵活性。

三、总结

责任链模式的优点:

  • 避免了过多的if - else判断语句连成一条调用链来处理请求;
  • 解耦了请求发起者和请求接收者,请求者可以不用知道是谁处理的,处理者也不用知道请求的全貌,并且增加新的请求接收者很方便,无需改动原有代码,符合开闭原则;

责任链模式的缺点:

  • 不能保证请求一定被请求接收者处理;
  • 存在性能问题,如果调用链特别长,因为使用类似递归一样的方法去判断是否能够处理该请求;
  • 调试不方便,有可能这个请求接收者没问题了,下一个请求接收者又出问题了;

责任链模式的使用场景:

  • 有多个对象可以处理同一个请求,哪个对象处理请求在运行时刻自动确定;
  • 如果想在不明确指定接受者的情况下,向多个对象的一个提交请求;
  • Java中异常的处理,层层抛出;
  • 拦截器链的使用;
  • JS 中的事件冒泡;
  • Apache Tomcat 对 Encoding 的处理;
  • SpringMVC中拦截器的处理;

责任链模式的注意事项:

  • 链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handle中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能;

设计模式 (二十二) 责任链模式相关推荐

  1. 行为型设计模式(1)—— 责任链模式(Chain of Responsibility Pattern)

    文章目录 1.简介 2.使用场景 3.示例 4.变种 参考文献 1.简介 经常听身边的同事说其在项目中用到了责任链模式,今天就来学习一下什么是责任链模式. 责任链模式(Chain of Respons ...

  2. java责任链模式做优惠_Java设计模式菜鸟系列(十八)责任链模式建模与实现

    责任链模式(ChainOfResponsibility): 有多个对象,每个对象持有下一个对象的引用,形成一条链,请求在这条链上传递,直到某一对象决定处理该请求,但是发出者并不清楚最终哪个对象会处理该 ...

  3. 设计模式(五)责任链模式

    一.什么是责任链模式?     责任链就是从一个起点发起请求,然后沿着任务链依次传递给每一个节点上的对象,直到有一个节点处理这个请求为止. 二.责任链模式实例实现? 1 public abstract ...

  4. Java设计模式(九)责任链模式 命令模式

    (十七)责任链模式 责任链模式的目的是通过给予多个对象处理请求的机会,已解除请求发送者与接受者之间的耦合关系.面对对象的开发力求对象之前保持松散耦合,确保对象各自的责任最小化.这种设计能够使得系统更加 ...

  5. 设计模式(四)责任链模式——责任链模式结构

    定义 责任链是行为型设计模式的一种,通过前一个处理者记录下一个处理者的方式形成一条处理链.客户端在调用时只需要将请求传递到责任上即可,无需关注链路中的具体的传递过程.而链路中内部的处理,是按照前一个处 ...

  6. Android设计模式详解之责任链模式

    前言 责任链模式是行为型设计模式: 定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 使用场景: 多 ...

  7. 设计模式第七讲-责任链模式

    简介 责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止. 图例 责任链-根据事情大小来决 ...

  8. 设计模式中的车轮战-责任链模式

    责任链模式在Android中的应用莫过于事件分发了,ViewGroup对事件分别给子View,从ViewTree的顶部至上而下地进行处理,直到事件被消化为止,这种方法在Android广播中也能看到 责 ...

  9. 设计模式(三)- 责任链模式

    职责链模式 文章目录 职责链模式 1.职责链模式 1.介绍 2.应用实例 代码 1.员工提交请求类:LeaveRequest 2. 抽象请假处理类:AbstractLeaveHandler 3.直接主 ...

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

    故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". 关羽过五关斩六将主要内容: 第一关,东岭关,斩守将孔秀. 东岭关 ...

最新文章

  1. 为所有PHP-FPM容器构建单独的NGinx Dock镜像
  2. 成功解决schedule.ScheduleValueError: Invalid time format
  3. android上河南星海科技_分数不高能上什么空乘学校?推荐下
  4. python-爬虫(1)
  5. 宝塔挂载linux硬盘,宝塔移动硬盘挂载Linux服务器挂载ntfs移动硬盘
  6. c 语言简单的聊天程序,写一个C-S程序,实现简单的聊天功能。(tcp/ip)
  7. 配置Windows 2008 R2 防火墙允许远程访问SQL Server 2008 R2 更改端口 连接字符串 IP+逗号+端口号...
  8. OpenStack —— DevStack配置安装
  9. Gradle Eclipse插件教程
  10. Weblogic之简介
  11. wince下的地址映射知识点滴
  12. mysql between 边界
  13. 游戏开发unity资源管理系列:查看AssetBundle的工具-AssetStudio
  14. Android-S模拟器
  15. 【第一组】第九次冲刺例会纪要
  16. uniapp打包app教程
  17. 何为文件系统,何为根文件系统?
  18. 云数据库PostgreSQL新人怎样上手
  19. 大数据毕设选题 - 机器学习餐厅销量预测(大数据 python)
  20. linux 用7zip解压rar,Linux7-rar文件的压缩及解压方法

热门文章

  1. html时间显示在div中,在html页面实时显示系统时间
  2. mysql增加超级用户_Mysql添加远程超级用户
  3. C/C++[codeup 1962]单词替换
  4. RNN神经网络- 吴恩达Andrew Ng 循环神经网络 NLP Transformers Week4 知识总结
  5. PyTorch搭建GoogLeNet模型(在CIFAR10数据集上准确率达到了85%)
  6. 260.只出现一次的数字III
  7. 用python写WordCount的MapReduce代码
  8. 借助Haproxy_exporter实现对MarathonLb的流量和负载实例业务的可用状态监控
  9. 【机器学习算法实现】主成分分析(PCA)——基于python+numpy
  10. 最新回归算法理解、实现及应用(1)线性回归