Apache Commons Chain – 阿帕奇共享链

最后修改: 2017年 8月 2日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

Apache Commons Chain is a library that uses the Chain of Responsibility pattern – generally used for organizing complex processing flows in which multiple receivers can process a request.

Apache Commons Chain是一个使用责任链模式的库–一般用于组织复杂的处理流程,其中多个接收者可以处理一个请求。

In this quick article, we’ll go through an example representing a withdrawal from an ATM.

在这篇快速文章中,我们将通过一个代表从自动取款机提款的例子。

2. Maven Dependency

2.Maven的依赖性

To start, we’ll import the latest version of this library using Maven:

首先,我们要用Maven导入这个库的最新版本。

<dependency>
    <groupId>commons-chain</groupId>
    <artifactId>commons-chain</artifactId>
    <version>1.2</version>
</dependency>

To check for the most recent version of this library – go here.

要检查这个库的最新版本 – 到这里

3. Example Chain

3.实例链

The ATM takes a number as an input and passes it down to handlers responsible for performing different actions. Those involve calculating numbers of bank notes to be dispensed, and sending a notification to the bank and customer about the transaction.

自动取款机将一个数字作为输入,并将其传递给负责执行不同行动的处理程序。这些动作包括计算要发放的纸币数量,并向银行和客户发送有关交易的通知。

4. Chain Context

4.产业链背景

The context represents the current state of an application, storing information about the transaction.

上下文代表了一个应用程序的当前状态,存储了关于交易的信息。

For our ATM withdrawal request, the information we need is:

对于我们的ATM提款请求,我们需要的信息是。

  • Total amount to be withdrawn
  • Number of 100 denomination notes
  • Number of 50 denomination notes
  • Number of 10 denomination notes
  • Amount left to be withdrawn

This state is defined in a class:

这种状态被定义在一个类中。

public class AtmRequestContext extends ContextBase {
    int totalAmountToBeWithdrawn;
    int noOfHundredsDispensed;
    int noOfFiftiesDispensed;
    int noOfTensDispensed;
    int amountLeftToBeWithdrawn;

    // standard setters & getters
}

5. Command

5 指挥

The Command takes the Context as an input and processes it.

命令Context作为输入并处理。

We’ll implement each of the steps mentioned above as a Command:

我们将把上面提到的每个步骤作为一个命令来实现:

public class HundredDenominationDispenser implements Command {

    @Override
    public boolean execute(Context context) throws Exception {
        intamountLeftToBeWithdrawn = (int) context.get("amountLeftToBeWithdrawn);
        if (amountLeftToBeWithdrawn >= 100) {
            context.put("noOfHundredsDispensed", amountLeftToBeWithdrawn / 100);
            context.put("amountLeftToBeWithdrawn", amountLeftToBeWithdrawn % 100);
        }
        return false;
    }
}

The Commands for FiftyDenominationDispenser & TenDenominationDispenser are similar.

FiftyDenominationDispenserTenDenominationDispenserCommands是类似的。

6. Chain

6.链条

A Chain is a collection of commands to be executed in a specified order. Our Chain will consist of the above Commands and also an AuditFilter at the end:

一个是按指定顺序执行的命令的集合。我们的将由上述Commands和最后的AuditFilter组成。

public class AtmWithdrawalChain extends ChainBase {

    public AtmWithdrawalChain() {
        super();
        addCommand(new HundredDenominationDispenser());
        addCommand(new FiftyDenominationDispenser());
        addCommand(new TenDenominationDispenser());
        addCommand(new AuditFilter());
    }
}

When any Command in the Chain returns true, it forces the Chain to end.

中的任何命令返回true时,它迫使结束。

7. Filter

7.滤波器

A filter is also a Command but with a postProcess method that is called after the execution of the Chain.

过滤器也是一个命令,但是有一个postProcess方法,在执行链之后被调用。

Our Filter will send a notification to the customer & the bank:

我们的Filter将向客户和银行发送通知。

public class AuditFilter implements Filter {

    @Override
    public boolean postprocess(Context context, Exception exception) {
        // send notification to bank and user
        return false;
    }

    @Override
    public boolean execute(Context context) throws Exception {
        return false;
    }
}

8. Chain Catalog

8.连锁店目录

It is a collection of Chains and Commands with their logical names.

它是一个带有逻辑名称的命令的集合。

In our case, our Catalog will contain the AtmWithdrawalChain.

在我们的案例中,我们的目录将包含AtmWithdrawalChain.

public class AtmCatalog extends CatalogBase {

    public AtmCatalog() {
        super();
        addCommand("atmWithdrawalChain", new AtmWithdrawalChain());
    }
}

9. Using the Chain

9.使用链条

Let’s see how we can use the above Chain to process a withdrawal request. We’ll first create a Context and then pass it the Chain. The Chain will process the Context.

让我们看看我们如何使用上述Chain来处理一个提款请求。我们将首先创建一个Context,然后将Chain传递给它。Chain将处理Context。将处理上下文。

We’ll write a test case to demonstrate our AtmWithdrawalChain:

我们将写一个测试案例来演示我们的AtmWithdrawalChain:

public class AtmChainTest {

    @Test
    public void givenInputsToContext_whenAppliedChain_thenExpectedContext() throws Exception {
        Context context = new AtmRequestContext();
        context.put("totalAmountToBeWithdrawn", 460);
        context.put("amountLeftToBeWithdrawn", 460);
        
        Catalog catalog = new AtmCatalog();
        Command atmWithdrawalChain = catalog.getCommand("atmWithdrawalChain");
        
        atmWithdrawalChain.execute(context);
        
        assertEquals(460, (int) context.get("totalAmountToBeWithdrawn"));
        assertEquals(0, (int) context.get("amountLeftToBeWithdrawn"));
        assertEquals(4, (int) context.get("noOfHundredsDispensed"));
        assertEquals(1, (int) context.get("noOfFiftiesDispensed"));
        assertEquals(1, (int) context.get("noOfTensDispensed"));
    }
}

10. Conclusion

10.结论

In this tutorial, we explored a practical scenario using the Apache’s Apache Commons Chain library – which you can read more about here.

在本教程中,我们使用Apache的Apache Commons Chain库探索了一个实际场景–你可以在这里阅读更多关于Apache Commons Chain库的信息

And, as always, the code for this article is available over on Github.

而且,像往常一样,这篇文章的代码可以在Github上找到