Skip to content

Template Method Pattern — Define Algorithm Skeleton, Let Subclasses Fill Details

DodaTech Updated 2026-06-24 4 min read

What You'll Learn

You will learn how the Template Method pattern defines the invariant parts of an algorithm in a base class while letting subclasses override specific steps. You will also understand the distinction between abstract methods (must override) and hook methods (optional override).

Why It Matters

When multiple algorithms share the same overall structure but differ in individual steps, duplicating the structure across each implementation leads to maintenance nightmares. Template Method captures the skeleton once and allows controlled customisation at designated hook points. Consider data mining: loading data from CSV, JSON, and XML all follow "load, clean, parse, analyse, report" but each has different Parsing logic. Template Method keeps the pipeline structure in one place.

Real-World Use

Data mining frameworks follow a standard pipeline: load data, clean data, transform, analyse, visualise. Each step varies by data source. DodaTech's data ingestion framework provides a template for reading, validating, transforming, and loading data, with subclasses overriding only the source-specific steps. Adding a new data source like Parquet means writing a new subclass with just the loading and Parsing logic — the rest of the pipeline is inherited.

The Pattern

AbstractClass defines the Template Method containing the algorithm skeleton. Primitive operations are abstract; hook methods have default implementations that subclasses may override.

from abc import ABC, abstractmethod

class DataMiner(ABC):
    def mine(self, path: str) -> str:
        data = self.load_data(path)
        cleaned = self.clean_data(data)
        parsed = self.parse_data(cleaned)
        result = self.analyze(parsed)
        self.generate_report(result)
        return self.get_report()

    @abstractmethod
    def load_data(self, path: str) -> str:
        pass

    def clean_data(self, data: str) -> str:
        return data.strip()

    @abstractmethod
    def parse_data(self, data: str) -> list:
        pass

    def analyze(self, data: list) -> dict:
        return {"count": len(data), "items": data}

    def generate_report(self, result: dict):
        print(f"Report: {result['count']} items found")

    def get_report(self) -> str:
        return "Mining complete"

class CSVMiner(DataMiner):
    def load_data(self, path: str) -> str:
        return "name,age\nAlice,30\nBob,25\n"

    def parse_data(self, data: str) -> list:
        lines = data.strip().split("\n")
        return [line.split(",") for line in lines[1:]]

class JSONMiner(DataMiner):
    def load_data(self, path: str) -> str:
        return '[{"name":"Alice","age":30},{"name":"Bob","age":25}]'

    def parse_data(self, data: str) -> list:
        import json
        return json.loads(data)
for miner in [CSVMiner(), JSONMiner()]:
    print(type(miner).__name__, miner.mine("dummy.txt"))
    print("---")
CSVMiner
Report: 2 items found
Mining complete
---
JSONMiner
Report: 2 items found
Mining complete
---

Structure

classDiagram
    class AbstractClass {
        +templateMethod()
        #primitiveOperation1()
        #primitiveOperation2()
        #hook()
    }
    class ConcreteClassA {
        #primitiveOperation1()
        #primitiveOperation2()
    }
    class ConcreteClassB {
        #primitiveOperation1()
        #primitiveOperation2()
    }
    ConcreteClassA --|> AbstractClass
    ConcreteClassB --|> AbstractClass

Real-World Usage

  • Java AbstractList — provides <a href="/design-patterns/iterator/">Iterator</a>() and listIterator() templates; subclasses implement get() and size().
  • Python's unittest.TestCasesetUp(), runTest(), tearDown() form the template of every test case.
  • Spring JdbcTemplate — the Template Method handles connection management while subclasses provide SQL and row mapping.
  • Apache Camel routesconfigure() is a Template Method where route definitions are plugged into the engine.

Pros and Cons

Pros Cons
Reuses common algorithm structure Increases inheritance depth
Controlled customisation at hook points Hard to follow the flow across inheritance levels
Follows the Hollywood Principle Every subclass must implement all abstract steps
Core algorithm is protected from modification Template methods can become too rigid for complex variations

The data miner example shows the Template Method mine() which calls a sequence of steps. load_data() and parse_data() are abstract — each subclass must implement them. clean_data() and analyze() have default implementations — subclasses can override if needed. This is the Hollywood Principle in action: "Don't call us, we'll call you."

Practice Questions

  1. Implement a Game template with initialize(), playTurn(), and endGame() steps — then create Chess and Monopoly variants.
  2. How would you decide whether a step should be abstract (must override), virtual with default (can override), or a hook (optional no-op)?
  3. What are the risks of adding new steps to the Template Method after subclasses have been written?
  4. Compare Template Method with Strategy — when would you choose one over the other for an algorithm that varies in multiple steps?

Challenge

Refactor the DataMiner template to support an optional validate_data() hook step between cleaning and Parsing. Ensure existing subclasses work without modification.

Real-World Task

Identify a duplicated algorithm structure in your codebase — two or more methods that follow the same sequence of operations with variant steps. Refactor them using Template Method and use DodaTech's code lineage tool to track subclass overrides.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro