转自JAVA设计模式之责任链模式(职责链模式)​​​​​​​

责任链/职责链(Chain of Responsibility)模式的定义

为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

责任链模式优缺点

责任链模式是一种对象行为型模式,其主要优点如下。

  1. 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
  2. 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
  3. 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
  4. 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 或 switch-case 语句。
  5. 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

当过多的if…else分支导致代码难以维护时,考虑使用责任链模式进行业务拆分。

其主要缺点如下。

  1. 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  2. 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  3. 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

责任链模式的结构

  1. 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  2. 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  3. 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

责任链模式结构图

客户端设置责任链图 

责任链模式的应用实例

案例一:公司处理员工请假请求

//抽象处理者
public abstract class Handler {private Handler nextHandler;// 当前领导能审批通过的最多天数public int maxDay;protected Handler(int maxDay) {this.maxDay = maxDay;}// 设置责任链中下一个处理请求的对象public void setNextHandler(Handler handler) {nextHandler = handler;}protected void handleRequest(int day) {if (day <= maxDay) {reply(day);} else {if (nextHandler != null) {// 审批权限不够,交给责任链上的下一个审批者nextHandler.handleRequest(day);} else {System.out.println(day + "天请假,没有更高的领导审批了");}}}// 交由具体的handler来实现protected abstract void reply(int day);}
// 具体处理者-项目经理
public class ProjectManager extends Handler{public ProjectManager(int maxDay) {super(maxDay);}@Overrideprotected void reply(int day) {System.out.println(day+"天请假,项目经理直接审批通过");}
}// 具体处理者-部门经理
public class DepartmentHead extends Handler{public DepartmentHead(int maxDay) {super(maxDay);}@Overrideprotected void reply(int day) {System.out.println(day+"天请假,部门经理审批通过");}
}
//client建立责任链处理请求
public class Client {public static void main(String[] args) {Handler handler1 = new ProjectManager(5);Handler handler2 = new DepartmentHead(10);handler1.setNextHandler(handler2);// 总是从链式的首端发起请求handler1.handleRequest(2);handler1.handleRequest(3);handler1.handleRequest(8);handler1.handleRequest(12);}
}/**
2天请假,项目经理直接审批通过
3天请假,项目经理直接审批通过
8天请假,部门经理审批通过
12天请假,没有更高的领导审批了
*/

案例二:销售团队处理客户需求

销售团队的层级关系:

Sales:<=5%
Manager:<=30%
Director:<=40%
Vice President:<=50%
CEO:<=55%

PriceHandler:

/*** 价格处理人:负责处理客户的折扣申请* 使用抽象类作为Handler的载体,* 因为Handler需要有一个指向自身类型的引用,使用interface不方便* @author HCX**/
public abstract class PriceHandler {/*** 直接后继,用于传递请求* 指向自身类型的引用* protected:使子类都可以访问到*/protected PriceHandler successor;public void setSuccessor(PriceHandler successor) {this.successor = successor;}/*** 处理折扣请求* @param discount*/public abstract void processDiscount(float discount);}

Sales:

/*** 销售人员,可以批准5%以内的折扣* @author HCX**/
public class Sales extends PriceHandler {@Overridepublic void processDiscount(float discount) {if(discount <= 0.05){System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(),discount);}else{//让直接后继来处理successor.processDiscount(discount);}}}

Manager:

/*** 销售经理,可以批准30%以内的折扣* @author HCX**/
public class Manager extends PriceHandler{@Overridepublic void processDiscount(float discount) {if(discount <= 0.3){System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(),discount);}else{//超过直接传递给直接后继successor.processDiscount(discount);}}}

Director:

/*** 销售总监,可以批准40%以内的折扣* @author HCX**/
public class Director extends PriceHandler {@Overridepublic void processDiscount(float discount) {if(discount <= 0.4){System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(),discount);}else{//超过直接传递给直接后继successor.processDiscount(discount);}}}

VicePresident:

/*** 销售副总裁,可以批准50%以内的折扣* @author HCX**/
public class VicePresident extends PriceHandler {@Overridepublic void processDiscount(float discount) {if(discount <= 0.5){System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(),discount);}else{//超过直接传递给直接后继successor.processDiscount(discount);}}}

CEO:

/*** CEO,可以批准55%以内的折扣* 折扣超出55%,拒绝申请* @author HCX**/
public class CEO extends PriceHandler{@Overridepublic void processDiscount(float discount) {if(discount <= 0.55){System.out.format("%s批准了折扣:%.2f%n", this.getClass().getName(),discount);}else{//让直接后继来处理System.out.format("%s拒绝了折扣:%.2f%n", this.getClass().getName(),discount);}}}

PriceHandlerFactory:

public class PriceHandlerFactory {/*** 创建PriceHandler的工厂方法* @return*/public static PriceHandler createPriceHandler() {PriceHandler sales = new Sales();PriceHandler lead = new Lead();PriceHandler manager = new Manager();PriceHandler director = new Director();PriceHandler vicePresident = new VicePresident();PriceHandler ceo = new CEO();//设置直接后继sales.setSuccessor(lead);lead.setSuccessor(manager);manager.setSuccessor(director);director.setSuccessor(vicePresident);vicePresident.setSuccessor(ceo);return sales;}}

Customer:

/*** 客户,请求折扣* @author HCX**/
public class Customer {private PriceHandler priceHandler;public void setPriceHandler(PriceHandler priceHandler) {this.priceHandler = priceHandler;}//只关心折扣请求是否被处理了,不关心被谁处理的。public void requestDiscount(float discount){priceHandler.processDiscount(discount);}public static void main(String[] args) {Customer customer = new Customer();customer.setPriceHandler(PriceHandlerFactory.createPriceHandler());Random random = new Random();for(int i=1;i<100;i++){System.out.println(i+":");customer.requestDiscount(random.nextFloat());}}}

Customer类只依赖于PriceHandler和PriceHandlerFactory两个类,并没有依赖实现的PriceHandler:Sales和Manager等;因此耦合度较低。

责任链模式的应用实例

BaseCase接口

public interface BaseCase {// 所有 case 处理逻辑的方法void doSomething(String input, BaseCase baseCase);
}

责任链处理基类(改进版)

public class CaseChain implements BaseCase {// 所有 case 列表private List<BaseCase> mCaseList = new ArrayList<>();// 索引,用于遍历所有 case 列表private int index = 0;// 添加 casepublic CaseChain addBaseCase(BaseCase baseCase) {mCaseList.add(baseCase);return this;}@Overridepublic void doSomething(String input, BaseCase baseCase) {// 所有遍历完了,直接返回if (index == mCaseList.size())return;// 获取当前 caseBaseCase currentCase = mCaseList.get(index);// 修改索引值,以便下次回调获取下个节点,达到遍历效果index++;// 调用 当前 case 处理方法currentCase.doSomething(input, this);}
}

各个 case 实现接口

public class OneCase implements BaseCase {@Override public void doSomething(String input, BaseCase baseCase) {  if ("1".equals(input)) {     // TODO do something     System.out.println(getClass().getName());     return;  }   //当前没法处理,回调回去,让下一个去处理 baseCase.doSomething(input, baseCase);}
}public class TwoCase implements BaseCase {@Override public void doSomething(String input, BaseCase baseCase) {  if ("2".equals(input)) {     // TODO do something     System.out.println(getClass().getName());     return;  }   //当前没法处理,回调回去,让下一个去处理 baseCase.doSomething(input, baseCase);}
}public class DefaultCase implements BaseCase {@Override public void doSomething(String input, BaseCase baseCase) {  System.out.println(getClass().getName());     }
}

client建立责任链处理请求

public class Client {public static void main(String[] args) throws Exception {String input = "3";   CaseChain caseChain = new CaseChain();  caseChain.addBaseCase(new OneCase()).addBaseCase(new TwoCase()).addBaseCase(new DefaultCase());  caseChain.doSomething(input, caseChain);}
}
/**
com.example.designPattern.chain.improve.DefaultCase
*/

JAVA设计模式之责任链模式(职责链模式)相关推荐

  1. Java设计模式作业-责任链模式

    Java设计模式作业-责任链模式:Web过滤器 文章目录 前言 一.类图 二.代码及测试结果 1.Trouble类 2.Support类 3.CharSupport类 4.TypeTransformS ...

  2. Java设计模式系列--责任链模式(应用)

    原文网址:Java设计模式系列--责任链模式(应用)_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Java设计模式中的责任链模式的一些使用场景. 责任链模式的好处 符合单一职责原则 每个功能 ...

  3. Java设计模式之责任链模式(简单易懂)

    前言: 责任链模式(Chain of Responsibility): 使多个对象都有机会处理同一请求,从而避免请求的发送者和接受者之间的耦合关系,每个对象都是一个处理节点,将这些对象连成一条链,并沿 ...

  4. 责任链模式(职责链模式)(Chain of Responsibility Pattern)

    学校OA 系统的采购审批项目:需求是 采购员采购教学器材 如果金额小于等于5000, 由教学主任审批(0<=x<=5000) 如果金额小于等于10000, 由院长审批(5000<x& ...

  5. 15、设计模式-行为型模式-职责链模式

    职责链模式 很多情况下,在一个软件系统中可以处理某个请求的对象不止一个,例如SCM系统中的采购 单审批,主任.副董事长.董事长和董事会都可以处理采购单,他们可以构成一条处理采购 单的链式结构,采购单沿 ...

  6. C#设计模式学习笔记:(20)职责链模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8109100.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第八个模式--职 ...

  7. 《设计模式详解》行为型模式 - 职责链模式

    职责链模式 6.4 职责链模式 6.4.1 概述 6.4.2 结构 6.4.3 案例实现 6.4.4 优缺点 6.4.5 JavaWeb 源码 - FilterChain 完整的笔记目录:<设计 ...

  8. Java设计模式之结构型:装饰器模式

    一.什么是装饰器模式: 当需要对类的功能进行拓展时,一般可以使用继承,但如果需要拓展的功能种类很繁多,那势必会生成很多子类,增加系统的复杂性,并且使用继承实现功能拓展时,我们必须能够预见这些拓展功能, ...

  9. Java设计模式(7)装饰模式(Decorator模式)

    Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...

最新文章

  1. 【Linux部署】借助Docker部署Redis集群(Docker网卡创建+6个Redis集群搭建shell脚本)
  2. [TCP/IP] 关闭连接后为什么客户端最后还要等待2MSL
  3. daterangepicker 日期范围插件自定义 可选 年份
  4. FONT Awesome 图标
  5. java 自定义结构_java自定义构造二叉树及其遍历
  6. Linux看硬盘同步,从磁盘同步看linux的机制和策略
  7. 目标检测——初始学习率设置的学习笔记
  8. win10如果虚拟化服务器,Win10内置虚拟化技术Virtualization在哪里 Win10查看CPU是否支持VT步骤...
  9. 怎样彻底卸载电脑上的软件
  10. Unity制作AR图片和视频展示
  11. 深圳“托育”放大招!政府出钱帮你带娃啦!
  12. python中Could not find module “...atari_py\ale_interface\ale_c.dll‘ (or one of its dependence)
  13. 天问: 量子力学中的波函数到底表示什么?
  14. c++三国杀【免费复制】——转载
  15. 计算机专业eng4u,加拿大高中文凭ossd项目之ENG4U英语4U课程内容介绍!
  16. python中函数的定义意思
  17. golang 哪些类型可以作为map key
  18. 二分查找的迭代算法和递归算法
  19. vivonex3s和华为mate40哪个好
  20. xilinx FPGA普通IO作PLL时钟输入

热门文章

  1. 无法连接到逻辑磁盘管理器服务
  2. jquery绑定点击事件形参_JQuery 绑定事件时传递参数的实现方法
  3. 不需要专业的P图软件,你也能抠图!
  4. 计算机输入法知识讲解,26、认识输入法--电脑基础知识
  5. form表单提交以及用Jquery实现ajax提交form表单
  6. 使用Service和BroadcastReceiver实时监听网络状态
  7. 浏览器利用框架BeEF测试-成功截取微博账号
  8. 最小描述长度MDL(Minimum Description Length)及信息论介绍
  9. HyperWorks12.0
  10. iOS开发之系统发短信功能详解