The Template Method Pattern
The Template Method Pattern was described by Russ Olsen, in his Design Patterns in Ruby, as “probably the simplest of the original Gof [Gang of Four] patterns.” Personally, I find that this pattern requires a bit more knowledge of OOP terms than does, for example, the Observer Pattern in my previous post. Nevertheless, it remains fairly simple, and thus makes a great candidate for my second post on Software Design Patterns.
Imagine that you are creating a game in which the player gets to be mayor of a small town. Part of what you will need to program are workers to populate your town. In order to simulate an actual town, you will have different types of workers, such as police officers, firefighters, teachers, doctors, bankers, etc.
Despite their different occupations, each own of these workers follows a very similar set of steps in their day:
- Wake up
- Put on Work Clothes
- Get to Work
- Work 9 to 5 (hey — this is a make-believe world)
- Get Back Home
The problem here is that, while the steps are the same for each type of worker, the implementation details are different — i.e., both the police officer and the firefighter have to put on a uniform for work, but the uniform they put on are very different. The teachers and bankers in your town all have to get to work, but teachers in our town might all take the subway, while bankers all take the bus. In other words, the general algorithm is the same for each type of worker, but the implementation details differ!
The problem of having an algorithm that has to be followed, yet having the flexibility to vary the implementation of any particular step in that algorithm, is the problem that the Template Method Pattern is meant to solve.
Note: Unlike my post on the Observer Pattern, I was unable to come up with a novel “setup” for the Template Method Pattern. The idea of an abstract Worker class was taken from an excellent resource, SourceMaking.
How do I build a set of objects that all follow the same algorithm, but which vary the implementation of particular steps in that algorithm.
The Naive Solution
Let’s focus on our police officer and our firefighter for now. The naive solution to the problem we are having is to simply create two separate classes — PoliceOfficer and Firefighter — with no relation amongst the two whatsoever.
As you can see above, we have side-stepped the entire issue of dealing with the fact that both a PoliceOfficer and a Firefighter are going through the exact same steps — i.e., both of their complete_work_day methods are the same — and it is only the implementation details of one of those steps — i.e., put_on_work_clothes — that differs.
The problem with the naive solution are many. First, even though to us humans there is only one algorithm for complete_work_day, we have actually defined two separate algorithms from the point of view of the computer. If we ever need to modify the steps of complete_work_day, we have to do so in two different places. It’s only a matter of time until we update one and not the other. This problem only grows larger as we add other classes that must follow this same algorithm.
Secondly, while it makes sense for both of our classes to implement their own put_on_work_clothes method, it does not make sense for them to implement the rest of the steps of the algorithm, since each step is exactly the same for each of our workers.
Between defining a new algorithm each time we make a new worker and defining each step in our algorithm, there is a lot of duplicate code.
Let’s figure out a way to clean this up.
The Template Method Pattern provides / introduces a very rich language for describing the problem of having a known algorithm whose particulars may vary.
- An Abstract Class that contains knowledge of the parts of the algorithm that do not vary.
- A Skeletal / Template Method that defines the steps and order in which those steps are to be executed
- Hooks that define either default implementations for steps in the algorithm, or must be implemented in concrete classes
- One or More Concrete Classes which hold implementation details for certain steps.
In general, an Abstract Class is a class that is not meant to be instantiated. Instead, it is meant to provide default behavior which its child classes can resort to. In terms of the Template Method Pattern, the abstract class’s responsibility is to know the steps in the algorithm as well as what order those steps are to be executed in.
This knowledge — steps and order of execution — are stored in the abstract class’s template method, from which the Template Method Pattern gets its name.
The abstract class provides hooks. Hooks are a fancy way to describe methods defined on the abstract class, but which have a specialized purpose: if they are not over-written by a sub-class, hooks provide default implementations for a particular step in the algorithm. In other words, hooks are meant to be over-written by the sub-classes to the abstract class.
We mentioned that hook methods provide default implementations of a particular step in the algorithm. However, sometimes, a default implementation makes no sense, and we expect sub-classes to always implement their own version of that step. In such cases, it is often useful to have that step / method defined in the abstract class, and have the definition raise an error with a useful message. (Otherwise, if a developer doesn’t realize they need to implement that step in the sub-class, it might take them longer to track down what the problem is).
Finally, the Template Method Pattern introduces the concept of a Concrete Class. The concrete class is simply the class or classes that are sub-classed from the abstract class, are meant to be instantiated, and which have their own implementation of particular steps in the algorithm.
The Template Method Pattern Solution
Let’s revisit our PoliceOfficer and Firefighter classes, but this time using the Template Method Pattern to define an abstract Worker class. Pay special attention to the comments within the code:
As you can see, we now have to very light PoliceOfficer and Firefighter classes, which both inherit from the abstract class Worker. The Worker class knows, via the template method, how to execute the algorithm, and the sub-classes provide specific implementations of the steps that vary for their specific cases.
Variations on the Template Method Pattern
None that I am aware that do not also fall into their own software design patterns.
- The Strategy Method uses delegation to parts of an algorithm, while the Template Method Strategy uses inheritance.
- The Factory Method Pattern is a specialized form of the Template Method Pattern.