Template Design Pattern (original) (raw)

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.

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

Working

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

Uses

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

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

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

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

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 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.

Disadvantages

Despite its benefits, it has some limitations.