Skip to main content

Template Method

complexitypopularity

Fix the skeleton of an algorithm in a superclass and let subclasses override individual steps without touching its structure.

The problem

You are writing a data mining app that pulls structured facts out of corporate documents. Version one handled DOC files. Then CSV. Then, a month later, PDF.

Three classes, and they are suspiciously similar. Opening a file and parsing its bytes genuinely differs per format, fine. But analyzing the extracted data and composing the report? Character-for-character identical, copied three times. Worse, the client code that uses them is a stack of conditionals figuring out which class it is holding, because the three share no common type.

The same trap shows up anywhere a process has a fixed shape and variable details, such as the per-turn AI of a strategy game.

The solution

Break the algorithm into steps, turn each step into a method, and put the calls to those steps, in order, inside a single method in a superclass. That method is the template method, and subclasses are not allowed to override it.

Steps come in three flavors. Abstract steps have no body and every subclass must supply one. Optional steps ship a sensible default that subclasses may replace. Hooks are optional steps with an empty body, parked before and after the important moments, so a subclass can inject behavior at a defined extension point without being obliged to.

Then hoist. Anything the subclasses were duplicating moves up into the base class as an optional step, which is how the pattern deletes code rather than merely reorganizing it. What genuinely varies stays down in the subclasses. The client gets a common base type and can drop its conditionals.

GameLoop (client)GameAI.turn() (skeleton)OrcsAI overridesMonstersAI overridesorcsAI.turn()1collectResources()2buildStructures()3buildUnits()4attack()5sendWarriors(enemy.position)6monstersAI.turn()7collectResources()8
  1. 1The client calls one method. It does not know which race it is playing, and does not need to.
  2. 2Step one runs the default implementation from the base class. Shared code stays shared; no subclass duplicates it.
  3. 3Step two is abstract, so the call lands in the subclass. Orcs build farms, then barracks, then a stronghold.
  4. 4Step three, also abstract. Notice the skeleton is dictating the order, not the subclass.
  5. 5Step four is itself a template method: it decides scouting versus assault and then delegates. A class may have several.
  6. 6The branch inside attack() calls another abstract step, and the orcs decide they need six warriors before they commit.
  7. 7Same client code, same skeleton, next player. Nothing at the call site changed.
  8. 8Monsters override the optional step with an empty body. They do not gather, they do not build, and the algorithm survives that just fine.

Structure

Two boxes and one arrow: an abstract class holding the template method plus its steps, and concrete classes overriding some of them. It is the smallest structure in the catalogue, which is why so much code contains Template Method without anyone announcing it.

«abstract»GameAI+ turn() <<template>>collectResources()attack() <<template>># buildStructures() <<abstract>># buildUnits() <<abstract>># sendScouts(pos) <<abstract>># sendWarriors(pos) <<abstract>>ABSTRACTOrcsAIbuildStructures()buildUnits()sendScouts(pos)sendWarriors(pos)CONCRETEMonstersAIcollectResources()buildStructures()buildUnits()CONCRETEGameLoopplayers: GameAI[]tick()CLIENT
extendsuses

Code

Same example three ways: the per-turn AI of a strategy game, where every race plays the same four beats and fills them differently.

// Every race reimplements the same four beats, in the same order,
// with the same helper code copy-pasted between them.
class OrcsAI is
method turn() is
foreach (s in this.builtStructures) do
s.collect()
// Build farms, then barracks, then stronghold.
// Build peons and grunts.
enemy = closestEnemy()
if (enemy == null)
sendScouts(map.center)
else
sendWarriors(enemy.position)
 
class HumansAI is
method turn() is
foreach (s in this.builtStructures) do
s.collect() // identical to the orcs, character for character
// Build houses, then barracks, then a keep.
// Build peasants and footmen.
enemy = closestEnemy() // and so is this
if (enemy == null)
sendScouts(map.center)
else
sendWarriors(enemy.position)
 
// Change the turn order once and you edit every race. Miss one and that
// race quietly plays a different game. The client also needs conditionals
// to figure out which class it is holding.
// One skeleton, written once, in the superclass.
class GameAI is
method turn() is
collectResources()
buildStructures()
buildUnits()
attack()
 
// Shared step lives here and is inherited by everyone.
method collectResources() is
foreach (s in this.builtStructures) do
s.collect()
 
abstract method buildStructures()
abstract method buildUnits()
 
// A race is now just the differences:
class OrcsAI extends GameAI is
method buildStructures() is
// Farms, barracks, stronghold.
method buildUnits() is
// Peons and grunts.
 
// Adding a race is one subclass. Changing the turn order is one line,
// in one place, and every race obeys it immediately.
// The abstract class owns the algorithm. Its template method is a list of
// calls to steps, some implemented here, some left to subclasses.
class GameAI is
// The template method: the skeleton, and the part nobody overrides.
method turn() is
collectResources()
buildStructures()
buildUnits()
attack()
 
// An optional step: a working default that subclasses may replace.
method collectResources() is
foreach (s in this.builtStructures) do
s.collect()
 
// Abstract steps: every subclass must supply these.
abstract method buildStructures()
abstract method buildUnits()
 
// A class can have more than one template method.
method attack() is
enemy = closestEnemy()
if (enemy == null)
sendScouts(map.center)
else
sendWarriors(enemy.position)
 
abstract method sendScouts(position)
abstract method sendWarriors(position)
 
// Concrete classes fill in the abstract steps and leave the skeleton alone.
class OrcsAI extends GameAI is
method buildStructures() is
if (there are some resources) then
// Farms first, then barracks, then the stronghold.
 
method buildUnits() is
if (there are plenty of resources) then
if (there are no scouts)
// Build a peon and add it to the scouts group.
else
// Build a grunt and add it to the warriors group.
 
method sendScouts(position) is
if (scouts.length > 0) then
// Send the scouts to the position.
 
method sendWarriors(position) is
if (warriors.length > 5) then
// Only commit once the warband is big enough.
 
// Subclasses may also override the optional steps, including into nothing.
class MonstersAI extends GameAI is
method collectResources() is
// Monsters gather nothing.
 
method buildStructures() is
// Monsters build nothing.
 
method buildUnits() is
// Monsters spawn; they do not train.

When to use it

  • You want clients to extend particular steps of an algorithm but not its structure. The skeleton is the contract you are protecting.
  • Several classes implement nearly identical algorithms with minor differences, so any change to the algorithm means editing all of them.
  • You have duplicate code across sibling classes and a clear shared sequence underneath it, waiting to be hoisted.

Pitfalls

  • The skeleton becomes a cage. A client whose algorithm genuinely needs a different order is stuck. If that keeps happening, the shape was not as universal as you thought.
  • Liskov violations by omission. Overriding a working default with an empty body, as MonstersAI does, breaks a promise the superclass made. Sometimes correct, never free.
  • Step sprawl. Every step added to the template is a method every subclass author must reason about. Ten steps is a maintenance surface, not a design.
  • Inheritance lock-in. A subclass can extend exactly one template. If an object needs to vary along two axes, you want composition, which means Strategy or Bridge.

Don't confuse it with

  • Strategy. These two answer the same question from opposite directions, and the distinction is worth memorizing. Template Method is inheritance based: the variation lives in a subclass, is decided at the class level, and is fixed once the object exists. Strategy is composition based: the variation lives in a separate object, is decided per instance, and can be swapped mid-run. Reach for Template Method when the variants share real structure and the set of them is known; reach for Strategy when you need runtime swapping or the variants share nothing internally.
  • State. Also composition, also swappable, but State exists to model a lifecycle whose members trigger transitions into each other. Nothing in a Template Method hierarchy transitions into anything.
  • Factory Method. A special case of Template Method where the varying step is "which object should we instantiate". It also appears in the other direction, as one step inside a bigger template method.

Check yourself

Question 1 of 5

Which method is a subclass forbidden to override?