Skip to content
Sanfor2004
← All articles
Design PatternsDesign PatternsBehavioral PatternsPythonC++Software Engineering

Template Method (Behavioral Pattern)

By Ahmed (Sanfor) · 11 Sept 2026 · 5 min read
Different cooks follow the same sequence of recipe steps.

Start with the design patterns overview · Part 22 of 23 · Behavioral patterns

Define an algorithm’s stable skeleton while allowing selected steps to vary in subclasses. This article follows the example in my 23 Design Patterns repository, connecting the problem, participating classes, Python and C++20 implementations, and the trade-offs that decide whether to use it.

The Problem

Reports share begin, read, format and end steps but vary their data access or formatting.

Naive Solution

void text_report() { /* begin, read, format, end */ }
void html_report() { /* duplicated order, different format */ }

Why It Becomes a Problem

Separate complete report functions duplicate ordering and can drift when a shared step changes.

The Idea

Report::generate is nonvirtual and calls protected virtual read and format hooks in a fixed order.

Reading the illustration

A recipe fixes the order—prepare, cook, serve—but different chefs provide the ingredient-specific steps.

In the repository example, the same design idea addresses this software problem: Reports share begin, read, format and end steps but vary their data access or formatting.

Structure

Diagram · Python source · C++20 source

Template Method sketch map: Report::generate() leads through read() + format() to TextReport overrides.
Template Method: trace the example from caller through the pattern boundary to its collaborator or result. The arrows show flow, not ownership. Open the full-size diagram.
Report::generate()  -->  read() + format()  -->  TextReport overrides

Participants

Report owns the algorithm skeleton; TextReport implements variation points. The client calls generate through the public workflow.

Canonical roles in this example:

  • Abstract Class — The Template Method role that owns the algorithm skeleton and declares variable steps. Here: Report.
  • Concrete Class — The Template Method role that supplies the variable steps. Here: TextReport.
  • hook method — An extension operation called by a fixed workflow; it may have a default implementation. Here: read, format.

Python Example

The complete Python source is shown first.

class Report:
    def generate(self):
        print("Begin report")
        data = self.read()
        self.format(data)
        print("End report")

    def read(self):
        raise NotImplementedError

    def format(self, data):
        raise NotImplementedError


class TextReport(Report):
    def read(self):
        return "sales=42"

    def format(self, data):
        print(data)


if __name__ == "__main__":
    TextReport().generate()

Python Output

Begin report
sales=42
End report

Code Walkthrough

Report owns the algorithm skeleton; TextReport implements variation points. The client calls generate through the public workflow.

Start at the final call in the Python example. Follow the middle role in the diagram and compare how the C++20 version handles the same responsibility.

C++20 Example

#include <iostream>
#include <string>
#include <string_view>

class Report {
protected:
    virtual std::string read() const = 0;
    virtual void format(std::string_view data) const = 0;
public:
    virtual ~Report() = default;
    void generate() const {
        std::cout << "Begin report\n";
        const auto data = read();
        format(data);
        std::cout << "End report\n";
    }
};
class TextReport final : public Report {
    std::string read() const override { return "sales=42"; }
    void format(std::string_view data) const override { std::cout << data << '\n'; }
};
int main() { TextReport{}.generate(); }

C++20 Output

Begin report
sales=42
End report

When to Use

Use it for a stable sequence with a few well-defined subclass extension points.

Use cases

Import pipelines and report generation fit when the skeleton is stable.

When NOT to Use

Avoid it if steps must be rearranged at runtime (The period when a compiled program is executing) or composition (Building behavior by connecting objects that use or contain other objects) would make dependencies clearer.

Advantages

Shared ordering rules stay in the base and subclasses implement only their differences.

Trade-offs

Inheritance couples subclasses to the base protocol. End is not guaranteed if read or format throws; use RAII (Resource Acquisition Is Initialization: tie resource ownership to object lifetime so destruction releases it) for real resource cleanup rather than treating the final step as a destructor.

Strategy · Factory Method

Common Confusion

Strategy injects replaceable behavior. Template Method relies on inherited hooks. Factory Method can be one creation hook inside such a skeleton.

Terms to Remember

  • Template Method — Fix an algorithm’s sequence while subclasses implement selected steps.
  • Abstract Class — The Template Method role that owns the algorithm skeleton and declares variable steps. Example: Report.
  • Concrete Class — The Template Method role that supplies the variable steps. Example: TextReport.
  • hook method — An extension operation called by a fixed workflow; it may have a default implementation. Example: read, format.

Interview Vocabulary

  • algorithm skeleton — The fixed sequence of an algorithm whose selected steps can vary.
  • inheritance — Defining a derived class from a base class to reuse or specialize its contract and implementation.
  • Open/Closed Principle — Aim for open for extension, closed for modification at a useful, chosen boundary.

Interview Question

Why is generate nonvirtual while read and format are virtual? What invariants does that express?

Mini Challenge

Add CsvReport and verify the begin/end order; then simulate a formatting exception and discuss cleanup.

Compare the two versions

Both versions use Inheritance to keep the sequence in generate and vary individual steps. C++ marks the steps virtual and keeps the workflow non-virtual. Python can override any method, so keeping the sequence fixed is a design convention. Injected callables are an alternative when Composition fits better. The two examples express the same pattern responsibility; compare their setup and output before changing an input.

Check yourself

  1. Which method owns the step order, and which methods can vary?
  2. When would the naive solution on this page be easier to maintain? Give a concrete example.
  3. Change one input in the Python example. Predict the output and explain which responsibility handles the change.

Run and explore the example

The Python code comes from python/main.py, with expected output. The C++20 code comes from behavioral/template-method/cpp/main.cpp. Follow the repository’s C++20 build instructions to compile it and compare the result with expected.txt. The output demonstrates this example’s behavior; it does not cover every input or the challenge above.

The source example and adapted explanation are © 2026 Sanfor2004, provided under the MIT license. The sketchbook cover is an illustration preserved from this site’s original pattern lessons.

Continue the series

Ahmed (Sanfor)Backend and automation engineer in Alexandria. I build the systems businesses run on, and paint between deploys.

Keep reading

Design PatternsAbstract Factory (Creational Pattern)5 minDesign PatternsAdapter (Structural Pattern)4 minDesign PatternsBridge (Structural Pattern)5 min

Have manual work eating your week?

Book a free call