Template Design Pattern

Last Updated : 12 May, 2026

The Template Method Design Pattern is a behavioral design pattern that defines the overall structure (skeleton) of an algorithm in a base class. It allows subclasses to redefine or customize specific steps of the algorithm without changing its core structure.

  • Defines a base algorithm structure while allowing subclasses to override specific steps.
  • Promotes code reuse and ensures consistent behavior across implementations.
Template-Design-Pattern
Template Design Pattern

Components

Defines the key elements involved in implementing the Template Method Pattern.

class_diagram_of_template_method_design_pattern-2
Class Diagram
  • Abstract Class/Interface: Defines the template method (algorithm skeleton) with some steps implemented and others left abstract or as hooks for customization.
  • Template Method: Outlines the algorithm’s fixed structure by calling steps in order, often marked final to prevent changes.
  • Abstract/Hook Methods: Placeholder methods in the abstract class that subclasses implement or optionally override.
  • Concrete Subclasses: Provide implementations for abstract methods, customizing specific steps while preserving the overall algorithm.

Working

This pattern works by defining the overall algorithm in a base (abstract) class and letting subclasses customize specific steps.

  • The base class contains a template method that defines the fixed sequence of steps.
  • Some steps are implemented in the base class, while others are abstract or overridable.
  • Subclasses provide their own implementation for the variable steps.
  • The algorithm’s structure remains unchanged.

Uses

The Template Method Design Pattern is used to define the skeleton of an algorithm while allowing subclasses to customize specific steps.

  • Common Algorithm with Variations: When an algorithm has a common structure but differs in some steps or implementations, the Template Method pattern can help subclasses customize specific parts while encapsulating the common phases in a superclass.
  • Code Reusability: By specifying the common steps in one place, the Template Method design encourages code reuse when you have similar tasks or processes that must be executed in several contexts.
  • Enforcing Structure: It's useful when you want to provide some elements of an algorithm flexibility while maintaining a particular structure or set of steps.
  • Reducing Duplication: By centralizing common behavior in the abstract class and avoiding duplication of code in subclasses, the Template Method pattern helps in maintaining a clean and organized codebase.

Real-Life Example

Preparing beverages like tea and coffee.

The steps boil water -> add main ingredient -> pour into cup -> add extras remain the same.
Tea and coffee differ only in specific steps like adding tea leaves or coffee powder.

Implementation Example

Problem Statement

Consider a scenario where we have a process for making different types of beverages, such as tea and coffee. While the overall process of making beverages is similar (e.g., boiling water, adding ingredients), the specific steps and ingredients vary for each type of beverage.

Benefits of using Template Method Design Pattern in this scenario

  • Using the Template Method pattern in this scenario allows us to define a common structure for making beverages in a superclass while allowing subclasses to customize specific steps, such as adding ingredients, without changing the overall process.
  • This promotes code reuse, reduces duplication, and provides a flexible way to accommodate variations in beverage preparation.
class_diagram_of_template_method_design_pattern_1
Class Diagram

Let’s break down into the component wise code:

1. Abstract Class

C++
// Abstract class defining the template method
#include <iostream>

class BeverageMaker {
public:
    // Template method defining the overall process
    void makeBeverage() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    // Abstract methods to be implemented by subclasses
    virtual void brew() = 0;
    virtual void addCondiments() = 0;

    // Common methods
    void boilWater() {
        std::cout << "Boiling water" << std::endl;
    }

    void pourInCup() {
        std::cout << "Pouring into cup" << std::endl;
    }
};
Java
/* Abstract class defining the template method */
abstract class BeverageMaker {
    // Template method defining the overall process
    void makeBeverage() {
        this.boilWater();
        this.brew();
        this.pourInCup();
        this.addCondiments();
    }

    // Abstract methods to be implemented by subclasses
    abstract void brew();
    abstract void addCondiments();

    // Common methods
    void boilWater() {
        System.out.println("Boiling water");
    }

    void pourInCup() {
        System.out.println("Pouring into cup");
    }
}
Python
# Abstract class defining the template method
from abc import ABC, abstractmethod

class BeverageMaker(ABC):
    # Template method defining the overall process
    def make_beverage(self):
        self.boil_water()
        self.brew()
        self.pour_in_cup()
        self.add_condiments()

    # Abstract methods to be implemented by subclasses
    @abstractmethod
    def brew(self):
        pass

    @abstractmethod
    def add_condiments(self):
        pass

    # Common methods
    def boil_water(self):
        print("Boiling water")

    def pour_in_cup(self):
        print("Pouring into cup")
JavaScript
// Abstract class defining the template method
class BeverageMaker {
    // Template method defining the overall process
    makeBeverage() {
        this.boilWater();
        this.brew();
        this.pourInCup();
        this.addCondiments();
    }

    // Abstract methods to be implemented by subclasses
    brew() {
        throw new Error("Method 'brew()' must be implemented.");
    }

    addCondiments() {
        throw new Error("Method 'addCondiments()' must be implemented.");
    }

    // Common methods
    boilWater() {
        console.log("Boiling water");
    }

    pourInCup() {
        console.log("Pouring into cup");
    }
}

2. Concrete Class (TeaMaker)

C++
#include <iostream>

class BeverageMaker {
public:
    virtual void brew() = 0;
    virtual void addCondiments() = 0;
};

class TeaMaker : public BeverageMaker {
public:
    // Implementing abstract methods
    void brew() override {
        std::cout << "Steeping the tea" << std::endl;
    }

    void addCondiments() override {
        std::cout << "Adding lemon" << std::endl;
    }
};
Java
abstract class BeverageMaker {
    // Abstract methods to be implemented
    abstract void brew();
    abstract void addCondiments();
}

class TeaMaker extends BeverageMaker {
    // Implementing abstract methods
    @Override
    void brew() {
        System.out.println("Steeping the tea");
    }

    @Override
    void addCondiments() {
        System.out.println("Adding lemon");
    }
}
Python
class TeaMaker(BeverageMaker):
    # Implementing abstract methods
    def brew(self):
        print("Steeping the tea")

    def addCondiments(self):
        print("Adding lemon")
JavaScript
class TeaMaker extends BeverageMaker {
    // Implementing abstract methods
    brew() {
        console.log("Steeping the tea");
    }

    addCondiments() {
        console.log("Adding lemon");
    }
}

3. Concrete Class (CoffeeMaker)

C++
// Concrete subclass for making coffee
class CoffeeMaker : public BeverageMaker {
    // Implementing abstract methods
    void brew() override {
        std::cout << "Dripping coffee through filter" << std::endl;
    }

    void addCondiments() override {
        std::cout << "Adding sugar and milk" << std::endl;
    }
};
Java
/* Concrete subclass for making coffee */
class CoffeeMaker extends BeverageMaker {
    // Implementing abstract methods
    @Override
    void brew() {
        System.out.println("Dripping coffee through filter");
    }

    @Override
    void addCondiments() {
        System.out.println("Adding sugar and milk");
    }
}
Python
# Concrete subclass for making coffee
class CoffeeMaker(BeverageMaker):
    # Implementing abstract methods
    def brew(self):
        print("Dripping coffee through filter")

    def addCondiments(self):
        print("Adding sugar and milk")
JavaScript
// Concrete subclass for making coffee
class CoffeeMaker extends BeverageMaker {
    // Implementing abstract methods
    brew() {
        console.log('Dripping coffee through filter');
    }

    addCondiments() {
        console.log('Adding sugar and milk');
    }
}

Complete code for the above example

C++
#include <iostream>
using namespace std;

// Abstract class defining the template method
class BeverageMaker {
public:
    // Template method defining the overall process
    void makeBeverage() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    // Abstract methods to be implemented by subclasses
    virtual void brew() = 0;
    virtual void addCondiments() = 0;

    // Common methods
    void boilWater() {
        cout << "Boiling water" << endl;
    }

    void pourInCup() {
        cout << "Pouring into cup" << endl;
    }
};

// Concrete subclass for making tea
class TeaMaker : public BeverageMaker {
public:
    // Implementing abstract methods
    void brew() override {
        cout << "Steeping the tea" << endl;
    }

    void addCondiments() override {
        cout << "Adding lemon" << endl;
    }
};

// Concrete subclass for making coffee
class CoffeeMaker : public BeverageMaker {
public:
    // Implementing abstract methods
    void brew() override {
        cout << "Dripping coffee through filter" << endl;
    }

    void addCondiments() override {
        cout << "Adding sugar and milk" << endl;
    }
};

int main() {
    cout << "Making tea:" << endl;
    TeaMaker teaMaker;
    teaMaker.makeBeverage();

    cout << "\nMaking coffee:" << endl;
    CoffeeMaker coffeeMaker;
    coffeeMaker.makeBeverage();

    return 0;
}
Java
// Abstract class defining the template method
abstract class BeverageMaker {
    // Template method defining the overall process
    public final void makeBeverage() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    // Abstract methods to be implemented by subclasses
    abstract void brew();
    abstract void addCondiments();

    // Common methods
    void boilWater() {
        System.out.println("Boiling water");
    }

    void pourInCup() {
        System.out.println("Pouring into cup");
    }
}

// Concrete subclass for making tea
class TeaMaker extends BeverageMaker {
    // Implementing abstract methods
    @Override
    void brew() {
        System.out.println("Steeping the tea");
    }

    @Override
    void addCondiments() {
        System.out.println("Adding lemon");
    }
}

// Concrete subclass for making coffee
class CoffeeMaker extends BeverageMaker {
    // Implementing abstract methods
    @Override
    void brew() {
        System.out.println("Dripping coffee through filter");
    }

    @Override
    void addCondiments() {
        System.out.println("Adding sugar and milk");
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println("Making tea:");
        BeverageMaker teaMaker = new TeaMaker();
        teaMaker.makeBeverage();

        System.out.println("\nMaking coffee:");
        BeverageMaker coffeeMaker = new CoffeeMaker();
        coffeeMaker.makeBeverage();
    }
}
Python
# Abstract class defining the template method
from abc import ABC, abstractmethod

class BeverageMaker(ABC):
    # Template method defining the overall process
    def make_beverage(self):
        self.boil_water()
        self.brew()
        self.pour_in_cup()
        self.add_condiments()

    # Common methods
    def boil_water(self):
        print("Boiling water")

    def pour_in_cup(self):
        print("Pouring into cup")

    # Abstract methods to be implemented by subclasses
    @abstractmethod
    def brew(self):
        pass

    @abstractmethod
    def add_condiments(self):
        pass

# Concrete subclass for making tea
class TeaMaker(BeverageMaker):
    # Implementing abstract methods
    def brew(self):
        print("Steeping the tea")

    def add_condiments(self):
        print("Adding lemon")

# Concrete subclass for making coffee
class CoffeeMaker(BeverageMaker):
    # Implementing abstract methods
    def brew(self):
        print("Dripping coffee through filter")

    def add_condiments(self):
        print("Adding sugar and milk")

if __name__ == '__main__':
    print('Making tea:')
    tea_maker = TeaMaker()
    tea_maker.make_beverage()

    print('\nMaking coffee:')
    coffee_maker = CoffeeMaker()
    coffee_maker.make_beverage()
JavaScript
// Abstract class defining the template method
class BeverageMaker {
    // Template method defining the overall process
    makeBeverage() {
        this.boilWater();
        this.brew();
        this.pourInCup();
        this.addCondiments();
    }

    // Common methods
    boilWater() {
        console.log('Boiling water');
    }

    pourInCup() {
        console.log('Pouring into cup');
    }

    // Abstract methods to be implemented by subclasses
    brew() {
        throw new Error('Method brew() must be implemented.');
    }

    addCondiments() {
        throw new Error('Method addCondiments() must be implemented.');
    }
}

// Concrete subclass for making tea
class TeaMaker extends BeverageMaker {
    // Implementing abstract methods
    brew() {
        console.log('Steeping the tea');
    }

    addCondiments() {
        console.log('Adding lemon');
    }
}

// Concrete subclass for making coffee
class CoffeeMaker extends BeverageMaker {
    // Implementing abstract methods
    brew() {
        console.log('Dripping coffee through filter');
    }

    addCondiments() {
        console.log('Adding sugar and milk');
    }
}

console.log('Making tea:'); 
const teaMaker = new TeaMaker();
teaMaker.makeBeverage();

console.log('\nMaking coffee:'); 
const coffeeMaker = new CoffeeMaker();
coffeeMaker.makeBeverage();

Output
Making tea:
Boiling water
Steeping the tea
Pouring into cup
Adding lemon

Making coffee:
Boiling water
Dripping coffee through filter
Pouring into cup
Adding sugar and milk

Advantages

The pattern provides controlled flexibility and code reuse.

  • Promotes code reuse by placing common logic in one place
  • Ensures a consistent algorithm structure
  • Makes the system easier to extend

Disadvantages

Despite its benefits, it has some limitations.

  • Increases dependency on inheritance
  • Changes in the template method can affect all subclasses
  • Can be less flexible than composition-based patterns
Comment

Explore