Template Method Pattern: Defining the Steps, Letting Subclasses Fill in the Details
By Misbahul Munir4 min read678 words

Template Method Pattern: Defining the Steps, Letting Subclasses Fill in the Details

Backend Development
design pattern
behavioral pattern

Sometimes you have an algorithm with a fixed structure, but certain steps of the process need to be defined or customized by subclasses.

The Template Method Pattern defines the skeleton of an algorithm in a base class and allows subclasses to override specific steps without changing the overall algorithm’s flow.


Real-World Analogy

Think of making tea vs. making coffee:

  1. Boil water.
  2. Add tea leaves or coffee grounds.
  3. Pour into a cup.
  4. Add sugar/milk if desired.

The process (boil → brew → pour → add extras) is the same, but the brewing step changes depending on the drink.

Here, the recipe is the template method, and the different drinks provide their own variations for certain steps.


Real-World Backend Example

Let’s say you’re building a backend service that processes incoming file imports from different formats (CSV, JSON, XML).

The workflow is:

  1. Load file.
  2. Parse data.
  3. Validate records.
  4. Save to database.

The overall steps never change, but the parsing step varies depending on the file type.

Abstract class with Template Method

from abc import ABC, abstractmethod class FileImporter(ABC): def import_file(self, filepath): self.load_file(filepath) data = self.parse_data() self.validate_data(data) self.save_to_db(data) print("Import completed.\n") def load_file(self, filepath): print(f"Loading file: {filepath}") self.filepath = filepath @abstractmethod def parse_data(self): pass def validate_data(self, data): print(f"Validating {len(data)} records.") def save_to_db(self, data): print(f"Saving {len(data)} records to the database.")

Concrete implementations

import json import csv import xml.etree.ElementTree as ET class CSVImporter(FileImporter): def parse_data(self): print("Parsing CSV file...") with open(self.filepath, newline="") as csvfile: reader = csv.DictReader(csvfile) return list(reader) class JSONImporter(FileImporter): def parse_data(self): print("Parsing JSON file...") with open(self.filepath) as jsonfile: return json.load(jsonfile) class XMLImporter(FileImporter): def parse_data(self): print("Parsing XML file...") tree = ET.parse(self.filepath) root = tree.getroot() return [{child.tag: child.text for child in record} for record in root]

Example usage

if __name__ == "__main__": # These would normally be actual files, but let's mock them import tempfile # Create mock CSV file csv_path = tempfile.NamedTemporaryFile(delete=False, suffix=".csv").name with open(csv_path, "w", newline="") as f: writer = csv.DictWriter(f, fieldnames=["name", "age"]) writer.writeheader() writer.writerow({"name": "Alice", "age": 30}) writer.writerow({"name": "Bob", "age": 25}) # Create mock JSON file json_path = tempfile.NamedTemporaryFile(delete=False, suffix=".json").name with open(json_path, "w") as f: json.dump([{"name": "Charlie", "age": 28}], f) # Run imports CSVImporter().import_file(csv_path) JSONImporter().import_file(json_path)

Example Output:

Loading file: /tmp/tmpabcd.csv Parsing CSV file... Validating 2 records. Saving 2 records to the database. Import completed. Loading file: /tmp/tmpabcd.json Parsing JSON file... Validating 1 records. Saving 1 records to the database. Import completed.

Gotchas & Considerations

  1. Rigid Workflow
    • The Template Method fixes the order of steps — this is good for consistency but can limit flexibility if steps need to be reordered dynamically.
  2. Code Reuse
    • Shared steps are implemented in the base class, avoiding duplication across subclasses.
  3. Hook Methods
    • You can define optional “hook” methods in the base class for subclasses to override if needed.
  4. Abstract vs. Concrete Steps
    • Some steps can be implemented in the base class (common logic), others abstract (custom per subclass).

When to Use Template Method Pattern

  • You have a fixed algorithm but want certain steps to be customizable.
  • You want to enforce a consistent process across different implementations.
  • You want to reduce duplicate code across similar workflows.

Final Thoughts

The Template Method Pattern is excellent for creating consistent workflows with customizable steps. It ensures that the big picture process remains unchanged while allowing flexibility in the details.

In backend systems, it’s a great fit for ETL pipelines, data importers, payment workflows, and report generators where the sequence of steps is fixed, but the implementation of some steps varies.

When used wisely, it promotes code reuse, enforces standards, and keeps business processes consistent — making it a reliable tool for large and evolving backend systems.