Apache Commons Chain 简介
Contents
1.简介
Apache Commons Chain 是一个使用责任链模式 的库——通常用于组织复杂的处理流程,其中多个接收者可以处理一个请求。
在这篇快速文章中,我们将通过一个表示从 ATM 取款的示例。
2. Maven依赖
首先,我们将使用 Maven 导入该库的最新版本:
<dependency>
<groupId>commons-chain</groupId>
<artifactId>commons-chain</artifactId>
<version>1.2</version>
</dependency>
要检查这个库的最新版本——去这里 。
3. 示例链
ATM 将一个数字作为输入并将其传递给负责执行不同操作的处理程序。这些包括计算要分发的钞票数量,并向银行和客户发送有关交易的通知。
4. 链上下文
上下文表示应用程序的当前状态,存储有关事务的信息。 对于我们的 ATM 取款请求,我们需要的信息是:
- 提款总额
- 100面额纸币数量
- 50面额纸币数量
- 10面额纸币数量
- 剩余金额
此状态在一个类中定义:
public class AtmRequestContext extends ContextBase {
int totalAmountToBeWithdrawn;
int noOfHundredsDispensed;
int noOfFiftiesDispensed;
int noOfTensDispensed;
int amountLeftToBeWithdrawn;
// standard setters & getters
}
5. 命令
Command将Context作为输入并对其进行处理。
我们将把上面提到的每个步骤作为一个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;
}
}
FiftyDenominationDispenser和TenDenominationDispenser的Command类似。
6. 链
Chain是按指定顺序执行的命令的集合。我们的Chain将由上述Command和最后的AuditFilter 组成:
public class AtmWithdrawalChain extends ChainBase {
public AtmWithdrawalChain() {
super();
addCommand(new HundredDenominationDispenser());
addCommand(new FiftyDenominationDispenser());
addCommand(new TenDenominationDispenser());
addCommand(new AuditFilter());
}
}
当Chain中的任何Command返回 true 时,它会强制Chain结束。
7. 过滤
过滤器也是一个Command,但具有在链执行后调用的postProcess方法。
我们的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和Command的集合。
在我们的例子中,我们的CatalogBase将包含AtmWithdrawalChain。
public class AtmCatalog extends CatalogBase {
public AtmCatalog() {
super();
addCommand("atmWithdrawalChain", new AtmWithdrawalChain());
}
}
9. 使用链
让我们看看我们如何使用上述Chain来处理提款请求。我们将首先创建一个Context,然后将其传递给Chain。Chain将处理Context。
我们将编写一个测试用例来演示我们的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"));
}
}