Chain of Responsibility Design Pattern in Java(java中的责任链设计模式)

131 阅读6分钟

大家好,我是王元存! 今天给大家分享一篇外国友人的责任链设计模式。

关注我,每天分享一篇java技术(双语)!

既可以把英语学到,又可以把技术学好,不香嘛?

搜索框传播样式-白色版.png


Chain of responsibility design pattern is one of the behavioral design pattern.

责任链设计模式是行为设计模式的一种

640-1.jpg

Chain of responsibility pattern is used to achieve loose coupling in software design where a request from client is passed to a chain of objects to process them. Then the object in the chain will decide themselves who will be processing the request and whether the request is required to be sent to the next object in the chain or not.

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

01: Chain of Responsibility Pattern Example in JDK

JDK 中的责任链模式实例

Let’s see the example of chain of responsibility pattern in JDK and then we will proceed to implement a real life example of this pattern. We know that we can have multiple catch blocks in a try-catch block code. Here every catch block is kind of a processor to process that particular exception. So when any exception occurs in the try block, its send to the first catch block to process. If the catch block is not able to process it, it forwards the request to next object in chain i.e next catch block. If even the last catch block is not able to process it, the exception is thrown outside of the chain to the calling program.

让我们看看 JDK 的责任链模式的例子,然后我们将着手实现这种模式的真实例子。我们知道在 try-catch 块代码中可以有多个 catch 块。这里的每个 catch 块类似于处理特定异常的处理器。因此,当 try 块中发生任何异常时,将其发送到要处理的第一个 catch 块。如果 catch 块不能处理它,它将请求转发给链中的下一个对象,即下一个 catch 块。如果甚至最后一个 catch 块也不能处理它,则异常将被抛出链的外部以调用程序。

02: Chain of Responsibility Design Pattern Example(责任链设计模式实例)

One of the great example of Chain of Responsibility pattern is ATM Dispense machine. The user enters the amount to be dispensed and the machine dispense amount in terms of defined currency bills such as 50,20, 20, 10$ etc. If the user enters an amount that is not multiples of 10, it throws error. We will use Chain of Responsibility pattern to implement this solution. The chain will process the request in the same order as below image.

640.png

Note that we can implement this solution easily in a single program itself but then the complexity will increase and the solution will be tightly coupled. So we will create a chain of dispense systems to dispense bills of 50,20, 20 and 10$.

Note that we can implement this solution easily in a single program itself but then the complexity will increase and the solution will be tightly coupled. So we will create a chain of dispense systems to dispense bills of 50,20, 20 and 10$.

责任链模式的一个很好的例子就是 ATM 自动取款机。用户输入要分发的金额,机器分发的金额根据确定的货币单据,如50美元,20美元,10美元等。如果用户输入的金额不是10的倍数,则抛出错误。我们将使用责任链模式来实现这个解决方案。链将按照与下图相同的顺序处理请求。注意,我们可以很容易地在单个程序中实现这个解决方案,但随后复杂性会增加,解决方案将紧密耦合。因此,我们将创建一个分发系统链,分发50美元,20美元和10美元的账单。

03: Chain of Responsibility Design Pattern - Base Classes and Interface

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

We can create a class Currency that will store the amount to dispense and used by the chain implementations. Currency.java

我们可以创建一个类 Currency,它将存储链实现要分发和使用的数量

640-1.png

The base interface should have a method to define the next processor in the chain and the method that will process the request. Our ATM Dispense interface will look like below. DispenseChain.java

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

640-2.png

04: Chain of Responsibilities Pattern - Chain Implementations

责任链模式-链实现

We need to create different processor classes that will implement the DispenseChain interface and provide implementation of dispense methods. Since we are developing our system to work with three types of currency bills - 50,20, 20 and 10$, we will create three concrete implementations. Dollar50Dispenser.java

我们需要创建不同的处理器类来实现 DispenseChain 接口并提供分配方法的实现。因为我们正在开发我们的系统,使之能够与三种类型的货币票据(50美元、20美元和10美元)协同工作,所以我们将创建三个具体的实现。$50Dispenser.java

640-2.png

640-1.png

640-3.png

The important point to note here is the implementation of dispense method. You will notice that every implementation is trying to process the request and based on the amount, it might process some or full part of it. If one of the chain not able to process it fully, it sends the request to the next processor in chain to process the remaining request. If the processor is not able to process anything, it just forwards the same request to the next chain.

这里需要注意的重点是分配方法的实现。您将注意到,每个实现都试图处理请求,并且基于请求的数量,它可能处理请求的一部分或全部。如果链中的一个不能完全处理它,它将请求发送到链中的下一个处理器以处理剩余的请求。如果处理器不能处理任何事情,它只是将相同的请求转发给下一个链。

05: Chain of Responsibilities Design Pattern - Creating the Chain

责任链设计模式——创建责任链

This is a very important step and we should create the chain carefully, otherwise a processor might not be getting any request at all. For example, in our implementation if we keep the first processor chain as Dollar10Dispenser and then Dollar20Dispenser, then the request will never be forwarded to the second processor and the chain will become useless. Here is our ATM Dispenser implementation to process the user requested amount. 

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

640-4.png

When we run above application, we get output like below.

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

640-5.png

06: Chain of Responsibilities Design Pattern Class Diagram

Our ATM dispense example of chain of responsibility design pattern implementation looks like below image.

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

640-6.png

07: Chain of Responsibility Design Pattern Important Points

责任链设计模式要点

Client doesn’t know which part of the chain will be processing the request and it will send the request to the first object in the chain. For example, in our program ATMDispenseChain is unaware of who is processing the request to dispense the entered amount.

 客户端不知道链的哪一部分将处理请求,它将把请求发送到链中的第一个对象。例如,在我们的程序中,ATMDispenseChain 不知道是谁在处理分发输入金额的请求

Each object in the chain will have it’s own implementation to process the request, either full or partial or to send it to the next object in the chain.

链中的每个对象都有自己的实现来处理请求,可以是完整的或部分的,也可以将其发送到链中的下一个对象

Creating the chain carefully is very important otherwise there might be a case that the request will never be forwarded to a particular processor or there are no objects in the chain who are able to handle the request. In my implementation, I have added the check for the user entered amount to make sure it gets processed fully by all the processors but we might not check it and throw exception if the request reaches the last object and there are no further objects in the chain to forward the request to. This is a design decision.

仔细创建链非常重要,否则可能会出现请求永远不会被转发到特定处理器的情况,或者链中没有能够处理请求的对象。在我的实现中,我添加了对用户输入的金额的检查,以确保所有处理器都能完全处理它,但是如果请求到达最后一个对象并且链中没有其他对象可以转发请求,我们可能不会检查它并抛出异常。这是一个设计决定

Chain of Responsibility design pattern is good to achieve lose coupling but it comes with the trade-off of having a lot of implementation classes and maintenance problems if most of the code is common in all the implementations.

责任链设计模式可以很好地实现失去耦合,但是如果大部分代码在所有实现中都是通用的,那么就会产生大量的实现类和维护问题

08: Chain of Responsibility Pattern Examples in JDK

JDK 中的责任链模式示例

  • java.util.logging.Logger#log()

  • javax.servlet.Filter#doFilter() Filter # doFilter ()

关注我,每天学习一篇英语技术文章!!