Behavioral Pattern

Template Method

Define the skeleton of an algorithm in a base class and let subclasses override specific steps without changing the algorithm's structure.

Fixed recipe, custom steps.

The Template Method pattern defines the overall steps of an algorithm once, in a base class, but leaves some steps blank for subclasses to fill in. Like a recipe that says "prepare, cook, serve" — the order is fixed, but each dish decides how to cook.

bad.py
# Problem: duplicated recipe with tiny differences per report type.
def csv_report():
    data = fetch()
    rows = to_csv(data)
    write("out.csv", rows)
    log("done")

def pdf_report():
    data = fetch()                        # same steps…
    rows = to_pdf(data)                   # …only format differs
    write("out.pdf", rows)
    log("done")
good.py
# Fix: Template Method — fixed skeleton, subclasses fill in steps.
from abc import ABC, abstractmethod

class Report(ABC):
    def generate(self):                   # template — do not override lightly
        data = self.fetch()
        body = self.format(data)          # hook / abstract step
        self.write(body)
        self.log("done")

    def fetch(self): ...
    def write(self, body): ...
    def log(self, msg): ...

    @abstractmethod
    def format(self, data):
        """Subclasses customize only this step."""

class CsvReport(Report):
    def format(self, data): return to_csv(data)

class PdfReport(Report):
    def format(self, data): return to_pdf(data)

CsvReport().generate()                    # same recipe, different format

Hooks and inversion of control.

The base class has a template method that calls a mix of concrete steps, abstract steps (subclasses must implement), and hooks (optional steps with default/empty behavior subclasses may override).

  • Hollywood Principle — "don't call us, we'll call you": the base class controls the flow and calls down into subclass steps.
  • Code reuse — the invariant algorithm lives in one place; only the varying parts are overridden.
  • Enforced structure — often the template method is final so the skeleton can't be broken.

Trade-offs and relations.

  • vs Strategy — Template Method varies steps via inheritance (compile time, one algorithm skeleton); Strategy varies the whole algorithm via composition (runtime, swappable objects).
  • Inheritance downsides — tight base-subclass coupling, fragile base class, and no runtime swapping; favor composition when flexibility matters.
  • LSP care — overridden steps must honor the base algorithm's expectations, or the template breaks.
  • Real uses — framework lifecycle methods, AbstractList and other skeletal implementations, unit-test setup/teardown, and servlet/HTTP request handling flows.