My First Design Pattern — Template Method

Seri Oh
Capgemini Microsoft Blog
4 min readNov 20, 2023
Photo by Susan Holt Simpson on Unsplash

In the last year, I have embarked on a journey to become a developer. After several training sessions and exercises with my mentor, I quickly noticed there was a difference between becoming a developer and becoming a good one. After spending hours trying to get my spaghetti code to run and spending even more time later on trying to understand what it was doing and locate errors, with my mentor’s advice, I picked up Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides. I wanted to know how to write readable, reusable, and performant code and it turned out that some people had already come up with ways to do this and neatly packaged them up in a textbook, saving me a lot of time and effort.

This is the first blog post I intend to write in a series covering design patterns that I come across on my journey. I am by no means an expert but hopefully I can provide a few articles with high-level, introductory overviews using easy examples.

The Template Method Design Pattern

You can use the template method design pattern where you want subclasses to override steps in an algorithm without changing its structure in a base class. An abstract class relies on its subclasses to implement its abstract methods — personally, I find it easier to think of the abstract methods as ‘placeholders’ that can get overridden.

Example: Making a smoothie

Suppose you run a smoothie stand. Represented in code, your class for a strawberry smoothie may look like this:

public class StrawberrySmoothie
{
public void makeSmoothie()
{
addMilk();
addFruit();
blend();
}

public void addMilk()
{
Print("adding milk");
}

public void addFruit()
{
Print("adding strawberries and banana");
}

public void blend()
{
Print("blending");
}
}

Of course, you’ll need to provide variety for your customers! You may have a class like this for your protein smoothie.

public class ProteinSmoothie
{
public void makeSmoothie()
{
addMangoJuice();
addProtein();
addFruit();
blend();
}

public void addMangoJuice()
{
Print("adding mango juice");
}

public void addProtein()
{
Print("adding protein");
}

public void addFruit()
{
Print("adding mango and banana");
}

public void blend()
{
Print("blending");
}
}

Apart from minor differences, you can see it is already getting quite repetitive. If I wanted to change one of the printed outputs from “blending” to “blended” for example, I’d have to do that once for each smoothie— it may not take much time now, but what about when our smoothie shop becomes a success and offers 20 different varieties? Or what if I wanted to add some new smoothies to my menu with a new extra ingredient? Then I would have to add a method just to add it to every smoothie that requires it.

To save us doing this, we can instead make a generic parent class that abstracts out the different components— a base (e.g. milk/mango juice), the ingredients (e.g. strawberries/bananas), extras (e.g. protein).

Firstly, I create the abstract base class:

public abstract Smoothie()
{
public void makeSmoothie()
{
addBase();
addIngredients();

if (isExtrasNeeded())
{
addExtras();
}

blend();
}

abstract void addBase()
{
}

abstract void addIngredients()
{
}

public boolean isExtrasNeeded()
{
return false;
}

public void addExtras()
{
}

public void blend()
{
Print("blending");
}

The base class defines the ‘template’ for making a smoothie and the common methods between the recipes, in this case, they are adding the base, ingredients, extras (if needed) and blending. The abstract methods for adding the base and ingredients will be implemented in the child classes. When extras are needed, isExtrasNeeded will be overridden to return true in the child class and the addExtras method will be implemented.

Now our strawberry smoothie looks like this:

public StrawberrySmoothie() extends Smoothie
{
void addBase()
{
Print("adding milk");
}
void addIngredients()
{
Print("adding strawberry and banana");
}
}

The strawberry smoothie child class extends the Smoothie class from before. It inherits all the methods from the parent and overrides the ones for adding the base and ingredients. Similarly, here is the class for the protein smoothie:

public ProteinSmoothie() extends Smoothie
{
public boolean isExtrasNeeded()
{
return true;
}

void addBase()
{
Print("adding mango juice");
}

void addIngredients()
{
Print("adding mango and banana");
}

void addExtras()
{
Print("adding protein supplement");
}
}

The protein smoothie child class overrides the return value for isExtrasNeeded to true and implements the addBase, addIngredients, and addExtras methods. Now if I wanted to change the blend method, I could just do it once in the parent class and the change would be inherited in the child classes too. Additionally, if I wanted to make smoothies with a new extra like chocolate toppings, I can add it to addExtras without changing the template method (makeSmoothie) in the parent.

Now I can make a class to make my smoothies:

public class SmoothieMaker 
{
public static void main (String[] args)
{
StrawberrySmoothie orderOne = new StrawberrySmoothie();
orderOne.makeSmoothie();

ProteinSmoothie orderTwo = new ProteinSmoothie();
orderTwo.makeSmoothie();
}
}

It looks a lot neater now — instead of having a new class with repetitive methods for every smoothie, I can now have one generic class that all my smoothies inherit from and any differences in implementation (e.g. bases, ingredients, extras) are only in the child classes where they are needed.

Using the template method pattern, we have eliminated the duplicate code through inheritance. This promotes its reusability and makes it more efficient as subclasses can decide which methods to implement. However, it does have the disadvantage that the flow of the code can be hard to follow sometimes, making it more difficult to maintain and debug.

I hope this post has given you a helpful introduction to the Template Method design pattern. Stay tuned for the next design pattern in this series!

If you’re looking for your next career step, consider Capgemini and our best in class Microsoft practice. Open roles here.

--

--