Template Method Pattern

The Template Method Pattern is a behavioral design pattern that 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.

Umm 🤔… How does it make sense to define skeleton of an algorithm while deferring to subclasses for implementation of those steps??

I know… I know it sounds weird 😵‍💫.

Let’s jump right into an example to understand what this algorithm is all about.

Let us suppose we want to create a video game having two NPCs (Non Player Characters).

One of them is a Warrior and the other is a Mage.

Let’s suppose they have the following actions:

Warrior:

  • swings sword ⚔️
  • uses power strike move 💥
  • defends by raising shield 🛡️

Mage:

  • casts fireball 🔥
  • casts lightning 🌩️
  • defends by casting a magic barrier ✨

Let us now define the behavior of Warrior NPC

class WarriorNPC {
    private Random random = new Random();

    void takeTurn() {
        // Spawn up the Warrior NPC
        System.out.println("NPC enters the battlefield!");

        // Warrior performs powerful moves based on next random boolean
        if (random.nextBoolean()) {
            System.out.println("Warrior swings sword!");
        } else {
            System.out.println("Warrior uses POWER STRIKE");
        }

        // Warrior defends with a shield
        System.out.println("Warrior raises shield");
        
        // Turn ends for the Warrior
        System.out.println("Turn ends");
    }
}

…and the behavior of the Mage NPC.

class MageNPC {
    private int turnCounter = 0;

    void takeTurn() {
        // Spawn up the Warrior NPC
        System.out.println("NPC enters the battlefield!");

        // Mage performs magic based on even or odd counter
        turnCounter++;
        if (turnCounter % 2 == 0) {
            System.out.println("Mage casts Fireball");
        } else {
            System.out.println("Mage casts Lightning");
        }

        // Mage defends by casting a magic barrier
        System.out.println("Mage casts magic barrier");
        
        // Turn ends for Mage
        System.out.println("Turn ends");
    }
}

Our NPC characters look good. Let us now take turns to call our NPCs in our Game.

public class Game {
    public static void main(String[] args) {
        // Initialize the NPCs
        WarriorNPC warrior = new WarriorNPC();
        MageNPC mage = new MageNPC();

        // Take turns to call our NPCs
        warrior.takeTurn();
        mage.takeTurn();
      
    }
}

Nice, looks like our game is ready 😎.

But… there are a few 🤏 problems.

  • Although the NPCs function correctly, there is a significant amount of code duplication when comparing their behaviors. Both NPCs share identical logic for spawning and ending turns, with the primary distinction lying in how they execute their actions and handle defense.
  • If a new NPC character like a dragon 🐉 needs to be created, we are not yet enforcing a fixed order of steps to create it.

The Template Method

Let us now now try to understand the definition of Template method pattern again.

The Template Method Pattern defines the steps of an algorithm and allows subclasses to provide the implementation for one or more steps.

Let us try to implement Template Method pattern to solve the above mentioned problems.
We need some way to define a common structure for behaviors shared across all NPCs, while leaving certain steps open for individual NPCs to implement according to their unique characteristics.

But how do we achieve that 🤔.

Bingo💡
An abstract class gives us the shared blueprint, while letting each NPC write its own unique attack and defense in the game.

// Abstract Template
abstract class NPC {

    // Template Method
    public final void takeTurn() {
        spawn();          // handled by this class
        performAction();  // to be handled by subclass
        defend();         // to be handled by subclass
        endTurn();        // handled by this class
    }

    // Shared method across all NPCs
    private void spawn() {
        System.out.println("NPC enters the battlefield!");
    }

    // To be implemented by concrete NPC subclass
    protected abstract void performAction();
    // To be implemented by concrete NPC subclass
    protected abstract void defend();

    // Shared method across all NPCs
    private void endTurn() {
        System.out.println("Turn ends");
    }
}

Let us take a closer look at the template method:

    // Template Method
    public final void takeTurn() {

        spawn();                    // handled by this class
        performAction();      // to be handled by subclass
        defend();                  // to be handled by subclass
        endTurn();               // handled by this class

    }

The method takeTurn() in the above above abstract class is called a template method.
why??

Because:

  • It is a method, after all🤭 and,
  • It serves as a template for an algorithm – in this case, an algorithm to create NPCs.

In the template, each step of the algorithm is represented by a method. Some of these methods are handled by the abstract class and some are handled by the subclass.
The methods that need to be supplied by a subclass are declared abstract.
Also, you might have noticed by now that the template method is final to prevent subclasses from reworking the sequence of steps in the algorithm.

Alright, but we still need the concrete NPCs for the Game.
So let’s start with the Warrior.

class WarriorNPC extends NPC {
    Random random = new Random();

    @Override
    protected void performAction() {
        if (random.nextBoolean()) {
            System.out.println("Warrior swings sword!");
        } else {
            System.out.println("Warrior uses POWER STRIKE");
        }
    }

    @Override
    protected void defend() {
        System.out.println("Warrior raises shield");
    }
}

And then the Mage…

class MageNPC extends NPC {

    private int turnCounter = 0;

    @Override
    protected void performAction() {
        turnCounter++;

        if (turnCounter % 2 == 0) {
            System.out.println("Mage casts Fireball");
        } else {
            System.out.println("Mage casts Lightning");
        }
    }

    @Override
    protected void defend() {
        System.out.println("Mage casts magic barrier");
    }
}

And hence, using the template method pattern, we achieved the following:

  • Common logic was written once
  • Clear separation of fixed v/s variable behavior
  • A skeleton to add new NPCs

Hooks in Template Method

A hook is a method that is declared in the abstract class, but only given an empty or default implementation.
This gives the subclasses a choice to ignore or override this method.

In our example, suppose the mage defends only if the magic barrier is stronger than the attack otherwise they just disappear without defending (its a mage after all 🪄).

In order to know whether the magic barrier is stronger than the attack or not, the Mage needs shouldFaceOpponent() method, but of course our brave Warrior needs no such method.

However, there might be some other NPCs which also need shouldFaceOpponent().

Let us start by modifying our NPC abstract class.

// Abstract Template
abstract class NPC {
    // Template Method
    public final void takeTurn() {
        spawn();
        performAction();

        // Hook controls defending
        // Mage defends if shouldFaceOpponent
        // otherwise disappears (ends turn without defending)
        if (shouldFaceOpponent()) {
            defend();
        }

        endTurn();
    }

    protected void spawn() {
        System.out.println("NPC enters the battlefield!");
    }

    protected void endTurn() {
        System.out.println("Turn ends");
    }

    // Abstract methods (must be implemented by subclasses)
    protected abstract void performAction();
    protected abstract void defend();

    // Hook for optional defending (default = always defend)
    protected boolean shouldFaceOpponent() {
        return true;
    }
}

Since Warrior always defends, it does not need the hook.
Hence the Warrior concrete class has no changes, but since Mage defends only when shouldFaceOpponent() returns true, it has to define it’s own implementation of shouldFaceOpponent() hook.

class MageNPC extends NPC {

    private int turnCounter = 0;

    @Override
    protected void performAction() {
        turnCounter++;
        if (turnCounter % 2 == 0) {
            System.out.println("Mage casts Fireball");
        } else {
            System.out.println("Mage casts Lightning");
        }
    }

    @Override
    protected void defend() {
        System.out.println("Mage casts magic barrier");
    }

    // Hook: disappear instead of defending on even turns
    @Override
    protected boolean shouldFaceOpponent() {
        return turnCounter % 2 != 0; // only defend on odd turns
    }
}

To use the hook, we override it in our Mage subclass. Here the hook controls whether the Mage defends or disappears.

And just like that 🥁… you’ve wielded your very first Template Pattern in Java!
With your NPCs ready to swing swords, cast lightning, or vanish in a puff of smoke, you now have a reusable blueprint for orchestrating all sorts of game behaviors.

And with that, we’ve wrapped up the Template Method Design Pattern – you’re now fully equipped with everything you need to know on Template Method 🥳.