通俗易懂系列 | 设计模式(六):责任链模式

责任链设计模式是行为设计模式之一。

责任链模式用于在软件设计中实现松散耦合,其中来自客户端的请求被传递到对象链以处理它们。然后链中的对象将自己决定谁将处理请求以及是否需要将请求发送到链中的下一个对象。

JDK中的责任链模式示例#

让我们看一下JDK中责任链模式的例子,然后我们将继续实现这种模式的真实例子。我们知道在try-catch块代码中我们可以有多个catch块。这里每个catch块都是处理该特定异常的处理器。

因此当try块中发生任何异常时,它会发送到第一个catch块进行处理。如果catch块无法处理它,它会将请求转发到链中的下一个对象,即下一个catch块。如果即使最后一个catch块也无法处理它,那么异常将被抛出链接到调用程序。

责任链设计模式示例#

责任链模式的一个很好的例子是ATM分配机器。用户按照定义的货币账单输入要分配的金额和机器分配金额,例如50美元,20美元,10美元等。
如果用户输入的数量不是10的倍数,则会引发错误。我们将使用Chain of Responsibility模式来实现此解决方案。链将以与下图相同的顺序处理请求。


请注意,我们可以在单应用程序中轻松实现此解决方案,但随后复杂性将增加,解决方案将紧密耦合。因此,我们将创建一系列分配系统,以分配50美元,20美元和10美元的账单。

责任链设计模式 - 基类和接口#

我们可以创建一个类Currency来存储分配和链实现使用的数量。
Currency.java

package com.journaldev.design.chainofresponsibility;public class Currency {private int amount;public Currency(int amt){this.amount=amt;}public int getAmount(){return this.amount;}}

基接口应该有一个方法来定义链中的下一个处理器以及处理请求的方法。我们的ATM Dispense界面如下所示。
DispenseChain.java

package com.journaldev.design.chainofresponsibility;public interface DispenseChain {void setNextChain(DispenseChain nextChain);void dispense(Currency cur);}

责任链模式 - 链实现#

我们需要创建不同的处理器类来实现DispenseChain接口并提供分配方法的实现。由于我们正在开发我们的系统以使用三种类型的货币账单--50美元,20美元和10美元,我们将创建三个具体实施。
Dollar50Dispenser.java

package com.journaldev.design.chainofresponsibility;public class Dollar50Dispenser implements DispenseChain {private DispenseChain chain;@Overridepublic void setNextChain(DispenseChain nextChain) {this.chain=nextChain;}@Overridepublic void dispense(Currency cur) {if(cur.getAmount() >= 50){int num = cur.getAmount()/50;int remainder = cur.getAmount() % 50;System.out.println("Dispensing "+num+" 50$ note");if(remainder !=0) this.chain.dispense(new Currency(remainder));}else{this.chain.dispense(cur);}}}

Dollar20Dispenser.java

package com.journaldev.design.chainofresponsibility;public class Dollar20Dispenser implements DispenseChain{private DispenseChain chain;@Overridepublic void setNextChain(DispenseChain nextChain) {this.chain=nextChain;}@Overridepublic void dispense(Currency cur) {if(cur.getAmount() >= 20){int num = cur.getAmount()/20;int remainder = cur.getAmount() % 20;System.out.println("Dispensing "+num+" 20$ note");if(remainder !=0) this.chain.dispense(new Currency(remainder));}else{this.chain.dispense(cur);}}}

Dollar10Dispenser.java

package com.journaldev.design.chainofresponsibility;public class Dollar10Dispenser implements DispenseChain {private DispenseChain chain;@Overridepublic void setNextChain(DispenseChain nextChain) {this.chain=nextChain;}@Overridepublic void dispense(Currency cur) {if(cur.getAmount() >= 10){int num = cur.getAmount()/10;int remainder = cur.getAmount() % 10;System.out.println("Dispensing "+num+" 10$ note");if(remainder !=0) this.chain.dispense(new Currency(remainder));}else{this.chain.dispense(cur);}}}

这里要注意的重点是分配方法的实施。您会注意到每个实现都在尝试处理请求,并且根据数量,它可能会处理部分或全部部分。
如果其中一个链不能完全处理它,它会将请求发送到链中的下一个处理器以处理剩余的请求。如果处理器无法处理任何内容,它只会将相同的请求转发到下一个链。

责任链设计模式 - 创建链#

这是非常重要的一步,我们应该仔细创建链,否则处理器可能根本没有得到任何请求。例如,在我们的实现中,如果我们将第一个处理器链保持为Dollar10Dispenser然后Dollar20Dispenser,那么请求将永远不会被转发到第二个处理器,并且链将变得无用。

这是我们的ATM Dispenser实现,用于处理用户请求的数量。

ATMDispenseChain.java

package com.journaldev.design.chainofresponsibility;import java.util.Scanner;public class ATMDispenseChain {private DispenseChain c1;public ATMDispenseChain() {// initialize the chainthis.c1 = new Dollar50Dispenser();DispenseChain c2 = new Dollar20Dispenser();DispenseChain c3 = new Dollar10Dispenser();// set the chain of responsibilityc1.setNextChain(c2);c2.setNextChain(c3);}public static void main(String[] args) {ATMDispenseChain atmDispenser = new ATMDispenseChain();while (true) {int amount = 0;System.out.println("Enter amount to dispense");Scanner input = new Scanner(System.in);amount = input.nextInt();if (amount % 10 != 0) {System.out.println("Amount should be in multiple of 10s.");return;}// process the requestatmDispenser.c1.dispense(new Currency(amount));}}}

当我们运行上面的应用程序时,我们得到如下的输出。

Enter amount to dispense530Dispensing 10 50$ noteDispensing 1 20$ noteDispensing 1 10$ noteEnter amount to dispense100Dispensing 2 50$ noteEnter amount to dispense120Dispensing 2 50$ noteDispensing 1 20$ noteEnter amount to dispense15Amount should be in multiple of 10s.

责任链设计模式类图#

我们的ATM分配示例的责任链设计模式实现如下图所示。

责任链设计模式重点#

  • 客户端不知道链的哪个部分将处理请求,它将把请求发送到链中的第一个对象。例如,在我们的程序中,ATMDispenseChain不知道谁在处理分配输入金额的请求。
  • 链中的每个对象都有自己的实现来处理请求,全部或部分或将其发送到链中的下一个对象。
  • 链中的每个对象都应该引用链中的下一个对象来转发请求,它由java组成。
  • 仔细创建链非常重要,否则可能会出现请求永远不会转发到特定处理器或链中没有能够处理请求的对象的情况。在我的实现中,我添加了对用户输入数量的检查,以确保它被所有处理器完全处理,但是如果请求到达最后一个对象并且链中没有其他对象,我们可能不检查它并抛出异常将请求转发给。这是一个设计决定。
  • 责任链设计模式很好地实现了失去耦合,但如果大多数代码在所有实现中都很常见,那么它会带来很多实现类和维护问题的权衡。

JDK中的责任链模式示例#

  • java.util.logging.Logger#log()
  • javax.servlet.Filter#doFilter()

这就是责任链设计模式的全部内容,我希望你喜欢它,并且能够清楚你对这种设计模式的理解。

翻译:journaldev

(0)

相关推荐

  • PyPattyrn-一个简单而有效的python库,用于实现常见的设计模式

    PyPattyrn是一个python软件包,旨在使您更轻松,更快地将设计模式实现到您自己的项目中. 设计模式本质上不能直接转换为代码,因为它们只是对如何解决特定问题的描述.但是,许多常见的设计模式都具 ...

  • 免费下载《Java设计模式(第2版)》.pdf

    回复"面试"获取全套面试资料 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用. 设计模式是软件开发人员在软件开发过程中面临的一 ...

  • PHP设计模式之责任链模式

    PHP设计模式之责任链模式 责任链模式,属于对象行为型的设计模式. Gof类图及解释 GoF定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这 ...

  • [PHP小课堂]PHP设计模式之责任链模式

    [PHP小课堂]PHP设计模式之责任链模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 设计模式之责任链模式

    设计模式之责任链模式

  • 通俗易懂系列 | 设计模式(八):建造者模式

    介绍# 今天我们将研究java中的Builder模式.Builder 设计模式是一种创造性的设计模式,如工厂模式和抽象工厂模式. 当Object包含许多属性时,引入了Builder模式来解决Facto ...

  • 通俗易懂系列 | 设计模式(五):策略模式

    介绍# 策略设计模式是行为设计模式之一.当我们为特定任务使用多个算法时,使用策略模式,客户端决定在运行时使用的实际实现. 策略模式的最佳示例之一是Collections.sort()采用Compara ...

  • 通俗易懂系列 | 设计模式(一):模板模式

    实际开发中常常会遇到,代码骨架类似甚至相同,只是具体的实现不一样的场景.例如:流程都有开启.编辑.驳回.结束.每个流程都包含这几个步骤,不同的是不同的流程实例它们的内容不一样.共享单车都是先开锁.骑行 ...

  • 【5/25】责任链模式(Chain of Responsibility Pattern)

    这是<小游戏从0到1设计模式重构>系列内容第5篇,所有源码及资料在"程序员LIYI"公号回复"小游戏从0到1"获取. 这一小节我们尝试应用责任链模式 ...

  • 三国演义:责任链模式

    单例模式 模板方法模式 装饰器模式 门面模式 策略模式 委派模式 故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". ...

  • 责任链模式

    一.责任链模式介绍 1.定义与类型 为请求创建一个接收此次请求对象的链 类型:行为型 2.适用场景 一个请求的处理需要多个对象当中的一个或几个协作处理 3.优点 请求的发送者和接收者(请求的处理)解耦 ...