Design Patterns: Template Method Pattern

These notes were adapted from various readings detailed in the References section.


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 defines the steps of an algorithm, and allows for subclasses to provide the implementation for one, or more steps.

Let’s go back to the example of beverages. CaffeineBevereage for example can have Tea and Coffee as its subclasses. These two beverages mostly have the same ways in preparation aside from how to brew and add condiments. We can abstract the objects to a base class.

Within the base class, is a method which will take care of preparation in the beverage, but allow for different implementations in brewing and adding condiments.

abstract class CaffeineBeverage {
    prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }
    
    abstract brew();
    abstract addCondiments();
    
    boilWater() { ... }
    pourInCup() { ... }
}

Then, the subclasses can only take care in overriding the abstract methods of brew and addCondiments. When the prepareRecipe of the parent class is called, the overridden methods are executed.

There are some cool real world examples and variations which makes use of the Template pattern. Most popular tend to be standard library sorting algorithms in which a comparer function reference must be passed into a sorting call to perform a sort.

Another useful thing about the Template pattern is that we can create hooks for a class. Basically, a hook is a method that is declared in the parent class, but only given an empty, or default implementation. Logic will then “hook” onto these methods by calling them in various points of execution. Subclasses are then able to “hook” into this functionality by providing some override logic. Unit test frameworks do this. In these frameworks, the test runner implements the Template Method pattern with calls such as before, beforeEach, beforeAll, after, afterEach, afterAll, and etc. These by default, are no-op methods, but are overridden in the test to perform set up and teardown work.

The Template Method is different from the Strategy pattern in that the Template Method pattern still maintains control in which the way an algorithm is executed, only letting subclasses override some steps in the process. Whereas for the Strategy pattern, a class is allowed to completely override functionality.

References

  • Head First Design Patterns - Eric Freeman & Elisabeth Freeman - https://www.oreilly.com/library/view/head-first-design/0596007124/