Перейти к основному содержимому

Сеть Apache Commons

· 3 мин. чтения

1. Введение

Apache Commons Chain — это библиотека, использующая шаблон цепочки ответственности , который обычно используется для организации сложных потоков обработки, в которых несколько получателей могут обрабатывать запрос.

В этой быстрой статье мы рассмотрим пример, представляющий снятие средств в банкомате.

2. Зависимость от Maven

Для начала мы импортируем последнюю версию этой библиотеки с помощью Maven:

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

Чтобы проверить наличие самой последней версии этой библиотеки — перейдите сюда .

3. Пример цепочки

Банкомат принимает число в качестве входных данных и передает его обработчикам, отвечающим за выполнение различных действий. Они включают в себя подсчет количества банкнот, подлежащих выдаче, и отправку уведомления банку и клиенту о транзакции.

4. Контекст цепочки

Контекст представляет текущее состояние приложения, сохраняя информацию о транзакции.

Для нашего запроса на снятие средств в банкомате нам нужна следующая информация:

  • Общая сумма к выводу
  • Количество банкнот номиналом 100
  • Количество банкнот номиналом 50
  • Количество банкнот номиналом 10
  • Осталось вывести сумму

Это состояние определено в классе:

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

// standard setters & getters
}

5. Команда

Команда принимает контекст C в качестве входных данных и обрабатывает его .

Мы реализуем каждый из шагов, упомянутых выше, как команду:

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 аналогичны .

6. Цепь

Цепочка — это набор команд, которые должны выполняться в определенном порядке. Наша цепочка будет состоять из вышеуказанных Command s, а также AuditFilter в конце:

public class AtmWithdrawalChain extends ChainBase {

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

Когда какая-либо команда в цепочке возвращает значение true, это принудительно завершает цепочку .

7. Фильтр

Фильтр также является командой , но с методом постобработки , который вызывается после выполнения цепочки.

Наш фильтр отправит уведомление клиенту и банку:

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. Каталог цепей

Это набор цепочек и команд с их логическими именами.

В нашем случае наш Каталог будет содержать AtmWithdrawalChain.

public class AtmCatalog extends CatalogBase {

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

9. Использование цепочки

Давайте посмотрим, как мы можем использовать вышеуказанную цепочку для обработки запроса на вывод средств. Сначала мы создадим контекст , а затем передадим ему цепочку. Цепь будет обрабатывать контекст .

Мы напишем тестовый пример, чтобы продемонстрировать нашу 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. Заключение

В этом руководстве мы рассмотрели практический сценарий с использованием библиотеки Apache Commons Chain от Apache — подробнее о ней можно прочитать здесь .

И, как всегда, код для этой статьи доступен на Github .