Apache Commons Chain

1. Introduzione

Apache Commons Chain è una libreria che utilizza il pattern Chain of Responsibility, generalmente utilizzato per organizzare flussi di elaborazione complessi in cui più destinatari possono elaborare una richiesta.

In questo rapido articolo, esamineremo un esempio che rappresenta un prelievo da un bancomat.

2. Dipendenza da Maven

Per iniziare, importeremo l'ultima versione di questa libreria utilizzando Maven:

 commons-chain commons-chain 1.2  

Per verificare la versione più recente di questa libreria, vai qui.

3. Catena di esempio

L'ATM prende un numero come input e lo trasmette ai gestori responsabili dell'esecuzione di diverse azioni. Questi comportano il calcolo del numero di banconote da erogare e l'invio di una notifica alla banca e al cliente sulla transazione.

4. Contesto catena

Il contesto rappresenta lo stato corrente di un'applicazione, memorizzando le informazioni sulla transazione.

Per la nostra richiesta di prelievo tramite bancomat, le informazioni di cui abbiamo bisogno sono:

  • Importo totale da prelevare
  • Numero di 100 banconote di taglio
  • Numero di 50 banconote in taglio
  • Numero di 10 banconote in taglio
  • Importo rimasto da ritirare

Questo stato è definito in una classe:

public class AtmRequestContext extends ContextBase { int totalAmountToBeWithdrawn; int noOfHundredsDispensed; int noOfFiftiesDispensed; int noOfTensDispensed; int amountLeftToBeWithdrawn; // standard setters & getters }

5. Comando

Il comando prende il C ONTESTO come ingresso e lo elabora.

Implementeremo ciascuno dei passaggi sopra menzionati come un comando:

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; } } 

I comandi per FiftyDenominationDispenser e TenDenominationDispenser sono simili.

6. Catena

Una catena è una raccolta di comandi da eseguire in un ordine specificato. La nostra catena sarà composta dai comandi di cui sopra e anche un AuditFilter alla fine:

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

Quando un comando nella catena restituisce vero, forza la fine della catena .

7. Filtro

Un filtro è anche un comando ma con un metodo postProcess che viene chiamato dopo l'esecuzione della catena.

Il nostro filtro invierà una notifica al cliente e alla banca:

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. Catalogo delle catene

È una raccolta di catene e comandi con i loro nomi logici.

Nel nostro caso, il nostro Catalogo conterrà AtmWithdrawalChain.

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

9. Utilizzo della catena

Vediamo come possiamo utilizzare la catena di cui sopra per elaborare una richiesta di prelievo. Creeremo prima un contesto e poi lo passeremo alla catena. La catena elaborerà il contesto.

Scriveremo un test case per dimostrare il nostro 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. Conclusione

In questo tutorial, abbiamo esplorato uno scenario pratico utilizzando la libreria Apache Commons Chain di Apache, di cui puoi leggere ulteriori informazioni qui.

E, come sempre, il codice per questo articolo è disponibile su Github.