cv.cm

Coding · Design patterns

Template Method pattern explained with examples

5 min read

Short answer

Template Method is a behavioral design pattern that defines the skeleton of an algorithm in a base class method and lets subclasses override specific steps without changing the overall order. The base class decides what happens and when; subclasses decide how some of the steps are done. Optional steps with a default implementation are called hooks.

Intent and the problem it solves

Intent: define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. It is one of the behavioral patterns in the Gang of Four (GoF) book.

Imagine a reporting tool that exports data as CSV and as JSON. Both exporters do the same things in the same order: load the rows, check that there are any, format them, and add a footer with the row count. Only the formatting differs. If each exporter is written separately, the shared steps are copied, and a fix in one (for example, better handling of an empty result) is easily forgotten in the other.

With Template Method, a base class Exporter contains the export method with the fixed sequence of steps. The steps that vary are abstract methods. CsvExporter and JsonExporter implement only those.

Structure and participants

RoleResponsibility
Abstract classImplements the template method, which calls the steps in a fixed order; declares abstract steps and may provide hooks
Template methodThe public method that defines the algorithm; usually not meant to be overridden
Primitive operationAn abstract step that every subclass must implement
HookA step with a default (often empty) implementation that subclasses may override
Concrete classImplements the primitive operations and overrides hooks as needed

This design inverts control: the base class calls the subclass methods, not the other way around. This is sometimes called the Hollywood principle: "don't call us, we'll call you".

TypeScript implementation

export is the template method. format is a primitive operation that subclasses must implement, and header is a hook with an empty default.

type Row = { name: string; score: number };

abstract class Exporter {
  // The template method: fixed order of steps
  export(rows: Row[]): string {
    if (rows.length === 0) return "no data";
    const lines = [this.header(), this.format(rows), "rows: " + rows.length];
    return lines.filter((line) => line !== "").join("\n");
  }

  protected abstract format(rows: Row[]): string; // required step
  protected header(): string { return ""; }       // hook: optional step
}

class CsvExporter extends Exporter {
  protected header() { return "name,score"; }
  protected format(rows: Row[]) {
    return rows.map((r) => r.name + "," + r.score).join("\n");
  }
}

class JsonExporter extends Exporter {
  protected format(rows: Row[]) {
    return JSON.stringify(rows);
  }
}

const rows = [{ name: "Ana", score: 9 }, { name: "Ben", score: 7 }];
console.log(new CsvExporter().export(rows));
// name,score
// Ana,9
// Ben,7
// rows: 2
console.log(new JsonExporter().export(rows));
// [{"name":"Ana","score":9},{"name":"Ben","score":7}]
// rows: 2
console.log(new JsonExporter().export([])); // no data

The empty-data check and the footer live in one place. A new XML exporter would implement format and get the rest for free.

The same idea with composition

Inheritance is not the only way. You can pass the varying steps as functions, which turns the pattern into a close relative of Strategy and avoids class hierarchies:

type Row = { name: string; score: number };
type Steps = { format: (rows: Row[]) => string; header?: () => string };

function exportRows(rows: Row[], steps: Steps): string {
  if (rows.length === 0) return "no data";
  const lines = [steps.header?.() ?? "", steps.format(rows), "rows: " + rows.length];
  return lines.filter((line) => line !== "").join("\n");
}

console.log(exportRows([{ name: "Ana", score: 9 }], { format: (r) => r[0].name }));
// Ana
// rows: 1

Prefer this form when the steps are small and you do not need shared state in a base class, or when one exporter should combine steps from several sources.

When to use it and when not to

  • Use it when several classes run the same algorithm with only a few steps that differ, and you want to remove the duplicated parts.
  • Use it in frameworks that must control the order of operations while letting users customize steps, such as setup and teardown in tests.
  • Use hooks to offer optional extension points without forcing every subclass to implement them.
  • Do not use it when the variations are large or need to change at runtime. Strategy, with composition, is more flexible.
  • Avoid deep hierarchies of template methods. When subclasses override steps of subclasses of subclasses, the flow becomes hard to follow.

Real-world uses

  • Java's AbstractList: you implement get(int) and size(), and the base class provides iteration, indexOf, contains and other methods built on them.
  • Java's InputStream: subclasses implement the single-byte read(), and the base class implements read(byte[], int, int) by calling it (subclasses may override it for speed).
  • Test frameworks: JUnit, Python's unittest and others call setUp, the test method and tearDown in a fixed order, and you override the steps you need.
  • UI frameworks with life cycle methods, such as componentDidMount in React class components, call your methods at fixed points of their own algorithm.

Related patterns

PatternHow it differs from Template Method
StrategyStrategy replaces a whole algorithm by composition at runtime; Template Method fixes the algorithm and varies parts of it through inheritance at compile time.
Factory MethodA factory method is often one of the steps of a template method: the step that creates an object.
Hook functions and callbacksPassing callbacks into a fixed algorithm is the composition-based version of the same idea.

FAQ

What is a hook in the Template Method pattern?

A hook is a step that has a default implementation in the base class, often doing nothing. Subclasses may override it to add behavior at that point, but they do not have to.

What is the difference between Template Method and Strategy?

Template Method uses inheritance: the base class owns the algorithm and subclasses override steps. Strategy uses composition: the context delegates the whole algorithm to an object or function that can be swapped at runtime.

Should the template method itself be overridable?

No. Its purpose is to fix the order of steps. In Java or C# you can mark it final or non-virtual; in TypeScript you have to document it, because there is no final keyword.

How is Template Method related to Factory Method?

Factory Method is often a specialization of Template Method: the base class algorithm includes a step that creates an object, and subclasses decide which class to create.

All coding tutorials