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.
- Defines a base algorithm structure while allowing subclasses to override specific steps.
- Promotes code reuse and ensures consistent behavior across implementations.

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

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
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):
passConcrete 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