Template Method is a behavioral design pattern that let you define the skeleton of an algorithm and allow subclasses to redefine certain steps of the algorithm without changing its structure.
Imagine that you're writing an application for data mining office documents. Users would feed it documents in various formats (PDF, DOC, CSV) and receive useful uniform data instead.
The first version of the app could work only with DOC files. The following edition received the CSV support. A month later, you had added the ability to extract data from PDF files.
At some point, you noticed that all three parsing algorithms have a lot of similar code. While they were quite different in dealing with file formats, the data extraction and analysis had been almost identical for all formats. Hence, it would be nice to get rid of the code duplication, leaving the algorithm structure intact.
There was another problem related to client code that used these algorithms. It had lots of conditional that were picking a proper course of action depending on the selected algorithms. If all three parsing classes were sharing a common interface or a base class, these conditional could be eliminated in favor of using polymorphism.
The Template Method pattern suggests to break down an algorithm into a series of steps, turn steps into methods and call them one by one inside a single "template" method.
Subclasses will be able to override particular steps, but not the actual template method, leaving the algorithm structure unchanged.
In our data mining app, we could create a common base class for all three parsing algorithms. The crucial part of the class would be a template method that looks as this:
method templateMethod() is openDocument(); extractRawData(); parseRawData(); analyzeData(); closeDocument();
At first, you can declare the template method steps as
abstract, making all steps mandatory to override and forcing subclasses to provide their own implementations. But then, once all methods are in place, you can start scanning subclasses for similar code and pulling it into the base class, making these steps optional to override.
In our case, the steps of opening and closing documents will be different for all three file types, so there's no point in touching them. But other steps, such as parsing and analysis, can be pulled into the base class, allowing subclasses to share the common code.
There's another type of steps, called hooks. A hook is an optional step with an empty body. Thus, a template method will work even if a hook is not overridden. Usually, hooks are placed before and after crucial steps of algorithms, to provide subclasses with additional extension points.
Mass housing construction
Builders use the analogy of template methods for mass housing construction. There's a standard template for building a house that describes the construction steps: laying a foundation, framing, building walls, plumbing and wiring for water and electricity, etc.
But despite the standardization, builders can slightly alter each step to make a house a little bit different (i.e. add more windows, paint walls in a different color, ...)
Abstract class defines methods that act as steps of an algorithm, as well as the actual template method, which calls all of the steps in a certain order. The steps may either be declared
abstractor have some default implementation.
Concrete classes are obligated to implement the abstract steps of the template method, but may also override some optional steps already implemented in the abstract class. Concrete classes must not override the template method itself, though.
In this example, the Template Method pattern provides a layout for various branches of an artifical intelligence in a little strategy video game. It is simple to add a new race to the game: one just needs to create a new AI subclass and override the default methods declared in the base AI class.
class GameAI is // Template method should be defined in a base class. Its body is a set of // method class in a defined order. Usually, they are the steps of // some algorithm. method turn() is collectResources() buildStructures() buildUnits() attack() // Some of these steps may be implemented right in a base class. method collectResources() is foreach this.structures structure.collect() // And some of them could be defined as abstract. abstract method buildStructures() abstract method buildUnits() // By the way, a class can have several template methods. method attack() is enemy = closestEnemy() if (enemy == null) sendScouts(map.center) else sendWarriors(enemy.position) abstract method sendScouts(position) abstract method sendWarriors(position) // Subclasses can provide their own steps implementation as long as they don't // change the template method. class OrcsAI extends GameAI is method buildStructures() is If enough resources then Build farms, then barracks, then stronghold. method buildUnits() is If enough resources If scouts not exist, build 1 peon. Else build grunt. // ... method sendScouts(position) is If scouts exists, send scouts to position. method sendWarriors(position) is If grunts are more than 5, then send warriors to position. // Subclasses may not only implement abstract steps but also override default // steps from the base class. class MonstersAI extends GameAI is method collectResources() is Do nothing. method buildStructures() is Do nothing. method buildUnits() is Do nothing.
When subclasses should be able to extend the base algorithm without altering its structure.
The Template Method turns a monolithic algorithm into a series of individual steps, which can be easily extended by subclasses, while keeping the structure, defined in a superclass, intact.
When you have several classes that do similar things with only minor differences. When you alter one of the classes, you have to change others as well.
The Template Method makes it easy to extract similar steps of the algorithm into a base class. Code that differs between subclasses can remain inside subclasses.
How to Implement
Analyze the algorithm and see whether it is possible to break it down into steps. See which steps will be common for all subclasses and which one will be unique for all subclasses.
Create an abstract base class and declare a template method inside. Outline the algorithm structure inside template method using
abstractmethods. Think of making the method
finalto keep subclasses from overriding it.
It's fine if all of the steps will be abstract. However, some steps might benefit from having some default implementation. Subclasses won't be forced to implement those.
Think of adding hooks between the "proper" steps, as well as at the beginning and end of the template method.
For each variation of an algorithm, extend the abstract class by creating a new concrete subclass. It must implement all required steps, but may also override some optional ones.
Pros and Cons
- Helps to eliminate code duplication.
- You are limited with a skeleton of an existing algorithm.
- You might violate Liskov Substitution Principle while suppressing a default step implementation via a subclass.
- Template methods tend to be harder to maintain the more steps they have.
Relations with Other Patterns
Template Method uses inheritance to alter the algorithm by extending its parts in different classes. Strategy uses delegation to alter the object's behavior by replacing the nested strategy object. Template method works at the class level. Strategy allows you to change the behavior of individual objects.