Questo pattern permette di definire la struttura di un algoritmo lasciando alle sottoclassi il compito di implementarne alcuni passi come preferiscono. In questo modo si può ridefinire e personalizzare parte del comportamento nelle varie sottoclassi senza dover riscrivere più volte il codice in comune.
Template method è uno dei design pattern fondamentali della programmazione orientata agli oggetti definiti originariamente dalla cosiddetta Gang of Four, ovvero gli autori del libro Design Patterns.
Applicabilità
Il pattern è adatto nei seguenti casi:
quando si vuole implementare la parte invariante di un algoritmo una volta sola e lasciare che le sottoclassi implementino il comportamento che può variare
quando il comportamento comune di più classi può essere fattorizzato in una classe a parte per evitare di scrivere più volte lo stesso codice
per avere modo di controllare come le sottoclassi ereditano dalla superclasse, facendo in modo che i metodi template chiamino dei metodi "gancio" (hook) e impostarli come unici metodi sovrascrivibili.
Struttura
Il pattern è costituito da una classe astratta e da una o più classi concrete che la estendono con il meccanismo dell'ereditarietà.
Il pattern in un certo senso ribalta il meccanismo dell'ereditarietà secondo quello che viene scherzosamente chiamato "principio di Hollywood": non chiamarci, ti chiameremo noi. Normalmente sono le sottoclassi a chiamare i metodi delle classi genitrici; in questo pattern è il metodo template, appartenente alla classe genitrice, a chiamare i metodi specifici ridefiniti nelle sottoclassi.
La seguente descrizione utilizza un diagramma UML e richiami del linguaggio Java ma è facilmente applicabile a qualsiasi linguaggio OOP, come per esempio il C++.
AbstractClass
Definisce le operazioni primitive astratte che le classi concrete sottostanti andranno ad ampliare e implementa il metodo template che rappresenta lo scheletro dell'algoritmo.
Il metodo template può contenere del codice e chiamate ad altri metodi:
operazioni primitive, scritte in modo da dover essere ridefinite nelle sottoclassi. Rappresentano la parte variabile e personalizzabile dell'algoritmo. In Java sono metodi astratti (dichiarati con la parola chiave abstract). Nel diagramma sono PrimitiveOperation1() e PrimitiveOperation2().
metodi hook, ovvero metodi che possono essere ridefiniti a piacere oppure ereditati e utilizzati così come sono, a discrezione della sottoclasse. Rappresentano passi opzionali dell'algoritmo oppure implementazioni basilari che se necessario possono essere ridefinite nelle sottoclassi. Nel diagramma è il metodo doSomething() che la classe concreta sceglie di ridefinire.
metodi non sovrascrivibili che vincolano le implementazioni delle sottoclassi ad utilizzare l'implementazione definita dalla classe astratta. Nel diagramma il metodo doAbsolutelyThis() è dichiarato con la parola chiave final del linguaggio Java e quindi è protetto dal meccanismo dell'overriding.
ConcreteClass
Deve implementare le operazioni primitive astratte che eredita dalla superclasse, specificando così il comportamento per i passi variabili dell'algoritmo. Può scegliere di sovrascrivere o meno l'implementazione dei metodi hook. Per tutto il resto del codice si affida all'implementazione contenuta nella AbstractClass.
Implementazione
Una buona pratica è proteggere sia i metodi primitivi che il metodo template. In C++ le operazioni primitive possono essere dichiarate con la parola chiave protected, risultando così accessibili solo dal metodo template. Per evitare che il metodo template venga ridefinito nelle sottoclassi lo si può implementare come non virtuale, risultato che in Java è raggiunto dalla parola chiave final.
Per evitare che la scrittura di nuove sottoclassi diventi un compito oneroso è meglio cercare di minimizzare il numero di metodi primitivi.
Alcuni, per convenzione, utilizzano il prefisso Do nei nomi dei metodi che devono essere ridefiniti per facilitare la loro individuazione: per esempio DoRead, DoOpenDocument e così via.