[Design patterns in Java] Template Method
Il pattern Template Method definisce lo scheletro di un algoritmo e delega alle sottoclassi l'implementazione di uno o più passi senza modificarne la struttura.
CLASSIFICAZIONE
Il Template Method è classificato tra i pattern comportamentali (basati su classi).
PROBLEMA E CAMPO DI APPLICAZIONE
Supponiamo di dover realizzare un algoritmo che può presentare delle varianti relativamente ad alcuni suoi passi.
Ad esempio consideriamo una struttura del genere:
- passo 1
- passo 2
- passo 3 <- può variare
- passo 4
dove i primi due e l'ultimo sono "costanti" mentre il terzo può presentare delle varianti.
La soluzione più banale e sconsigliabile sarebbe quella di creare tante versioni dell'algoritmo quante sono le varianti, limitandosi a modificare solo la parte relativa al passo 3 e duplicando tutto il resto del codice.
Senza contare che eventuali modifiche al codice "condiviso" andrebbero replicate a tutte le versioni prodotte.
Ecco che ci viene in aiuto proprio il pattern Template Method.
SOLUZIONE
L'idea di base è di realizzare tanti metodi quanti sono i passi dell'algoritmo, rendendo "astratti" (ovvero privi di implementazione) quelli che possono variare.
In questo modo la classe che li contiene diventa a sua volta astratta, quindi non istanziabile direttamente, e funge da classe base per quelle derivate corrispondenti alle diverse versioni dell'algoritmo.
I metodi non astratti sono dichiarati private
mentre quelli astratti protected
affinchè possano essere accessibili alle classi derivate per l'overriding.
private void step1() { System.out.println("Executing step 1"); }
private void step2() { System.out.println("Executing step 2"); }
protected abstract void step3();
Ovviamente nelle classi derivate sarà obbligatorio implementare i metodi astratti, mentre tutto il codice "comune" sarà ereditato direttamente senza alcuna duplicazione.
Ad esempio avremo qualcosa del genere (TemplateClass
è la classe astratta)
class ConcreteClass extends TemplateClass {
@Override
protected void step3() { System.out.println("Running step 3"); }
}
Per evitare che si possa modificare la sequenza dei passi e quindi la struttura dell'algoritmo, si introduce un nuovo metodo pubblico che chiameremo algorithm()
, il quale si limita ad invocare nel giusto ordine i metodi che rappresentano i vari step.
Tale metodo è anche final
così che non possa essere ridefinito nelle sottoclassi.
public final void algorithm() {
step1();
step2();
step3();
step4();
}
Con questa soluzione è molto semplice aggiungere una nuova variante all'algoritmo semplicemente creando una nuova classe derivata ed implementando i metodi astratti.
[VIDEO]