Skip to content

Template Method

Template Method defines the overall structure of an algorithm in one place — the template method — and defers selected steps to subclasses. The skeleton, including the fixed order of steps, lives in the base class; the parts that vary are overridable hooks. Subclasses change what happens at each step without changing the sequence.

Many tasks share the same shape but differ in the details. A data-processing pipeline always reads input, parses it, transforms the records, and writes the result — but a CSV source and a JSON source parse differently, and one report might filter rows that another keeps. Copying the whole pipeline for each variant duplicates the read-write scaffolding and invites them to drift apart over time.

The fixed part here is the order of steps; the varying part is the content of some of them. Template Method captures the order once in a base method that calls the individual steps in sequence. Subclasses override only the steps that differ. The control flow is owned by the base class, so every variant runs the steps in the same proven order — an example of the “don’t call us, we’ll call you” inversion of control.

classDiagram
  class Pipeline {
    <<abstract>>
    +run(raw) string
    #parse(raw)* 
    #transform(rows)
    #format(rows)* 
  }
  class CsvPipeline {
    #parse(raw)
    #format(rows)
  }
  class JsonPipeline {
    #parse(raw)
    #format(rows)
  }
  Pipeline <|-- CsvPipeline
  Pipeline <|-- JsonPipeline
The base Pipeline fixes run(); subclasses override the parse and format steps
  • Abstract class — defines the template method that calls the steps in a fixed order. Some steps are abstract (must be overridden), some are concrete defaults (may be overridden), and the template method itself is usually not overridden.
  • Concrete class — overrides the variable steps to specialise the algorithm.
  • Client — calls the template method and gets the whole algorithm, customised by whichever subclass it uses.

A data-processing pipeline whose run method fixes the read-parse-transform-format order, while subclasses supply the parse and format steps. Languages without classical inheritance express the same idea with composition or function fields.

abstract class Pipeline {
// The template method: a fixed sequence of steps.
run(raw: string): string {
const rows = this.parse(raw);
const kept = this.transform(rows);
return this.format(kept);
}
protected abstract parse(raw: string): string[];
// A default step subclasses may override.
protected transform(rows: string[]): string[] {
return rows.filter((r) => r.length > 0);
}
protected abstract format(rows: string[]): string;
}
class CsvPipeline extends Pipeline {
protected parse(raw: string): string[] {
return raw.split('\n');
}
protected format(rows: string[]): string {
return rows.join(',');
}
}
const csv = new CsvPipeline();
console.log(csv.run('a\nb\n\nc')); // "a,b,c"
  • Pro: removes duplication by keeping the common skeleton in one place.
  • Pro: the base class enforces the correct order of steps, so subclasses cannot accidentally reorder them.
  • Pro: new variants need only override the steps that differ.
  • Con: it relies on inheritance, which is rigid — a subclass is locked to one base algorithm.
  • Con: too many hooks make the base method hard to follow, and overriding the wrong step can subtly break the contract.
  • Strategy achieves variation through composition rather than inheritance; it can swap the whole algorithm at runtime, where Template Method varies fixed steps at subclass time.
  • Factory Method is often a step within a template method — the base algorithm calls an overridable creation step.
What does the template method itself define?
Which parts do subclasses change?
What inversion of control does Template Method embody?
What is a key limitation compared with Strategy?