The Template Method Pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
The Template Method Pattern gives an important technique for code reuse.
The template method’s abstract class may define concrete methods, abstract methods, and hooks.
Abstract methods are implemented by subclasses and thereby alter the algorithm to their needs.
Hooks are methods that do nothing or default behavior in the abstract class,
but may be overriden in the subclass to actually use it to manipulate the algorithm.
To prevent subclasses from chaning the algorithm in the template method, it is declared final
.
Notice, that hooks make it possible to alter the behavior of the algorithm in the template method even if it is declared final
.
The Template Method Pattern follows the Hollywood Principle, which guides us to put decision making in high-level modules that can decided how and when to call low-level modules: “don’t call us, we’ll call you”.
The Template Method Pattern is not always designed by inheritance, as shown in the following example.
Instead many algorithms in Java and C++, for example sort()
which implements the basic sorting algorithm for elements in a collection (List, Vector, HashMap, …). For user defined types this method requires that the type implements the intferface Comparable
, which declares a single method: compareTo()
. This method is used by the algorithm in sort()
to get the elements in the desired order.
The Pattern is a great design tool for creating frameworks, where the framework controls how something gets done,
but lets the user specify some details of the framework’s algorithm behavior. For example the paint()
method of Swing’s (Java GUI Toolkit) JFrame
container needs to be implemented by a user-defined Frame
class.
Related patterns are the Strategy Pattern and the Factory Method Pattern. The Template Method Pattern ecnapsulates algorithms by inheritance, whereas the Strategy Pattern does this by composition. The Factory Method Pattern is a specialization of the Template Method pattern. It has a (template) method to create an object.
The following example shows one possible implementation of the Template Method pattern. It is about producing coffee and tea. The steps for each beverage are similar:
- Boil some water
- Brew
- Coffee: Brew the coffee grinds
- Tea: Steep the tea bag in the water
- Pour beverage in a cup
- Add condiment
- Coffee: Add sugar and milk
- Add lemon
The two recipes are essentialy the same except for brewing and adding condiments.
The common steps are implemented in an abstract base class called CaffeineBeverageWithHook
because both beverages
contain caffeine. This class contains the template method prepareRecipe()
,
which serves as template for an algorithm, in this case, for making caffeinated beverages, and it is declared final
.
Using this keyword, avoids overriding the actual algorithm in subclasses.
The intention of subclasses is to implement the abstract
methods of the algorithm.
In this example these are brew()
and addCondiments()
.
Additionaly subclasses can override the orther methods but don’t have to,
because the default behavior is provided by the base class. The method customerWantsCondiments()
is the hook,
that implements default behavior in the base class but is intended to be overriden in the subclasses.
The subclasses CoffeeWithHook
and TeaWithHook
are implementing the abstract CaffeineBeverage
interface.
Specifically, the abstract methods need to be implemented and the hook method is optional.
In this example, both subclasses implement the same hook method which could be moved to the base class.
Here, the hook methods ask the user for input on adding condiments:
The TeaWithHook
implements the CaffeineBeverageWithHook
interface and implements the brew()
and addCondiments()
methods suitable for its receipe (algorithm). The hook method customerWantsCondiments()
is also adapted to ask for the condiments that can be added to the tea beverage, a lemon:
The following code shows a test of the two subclasses TeaWithHook
and CoffeeWithHook
with their specific receip
(algorithm) implementations that is invoked when calling the prepareReceipe()
method of the base class
CaffeineBeverageWithHook
:
The output of the program is the following when we answer y
for a lemon in our tea and no
for not adding milk and sugar to our coffee:
Comments