0 XP · 0 scenes

Template Method

Fix the steps of a recipe, let subclasses fill in some of them
The problem

Tea and Coffee classes each write the whole recipe.

The idea

Write the recipe once in a base class method (prepare) that calls step methods in a fixed order.

Reach for it when

Several classes share the same overall flow but differ in some steps

1

The picture from life

Making a hot drink follows one recipe: boil water, brew, pour into a cup, add extras. The order never changes. Tea brews by steeping leaves and adds lemon; coffee brews by filtering and adds milk. The recipe card is fixed; only two steps differ.

2

The problem

What goes wrong when you do not use it.

Tea and Coffee classes each write the whole recipe. The boil and pour steps are copied, and someone fixing a bug in one forgets the other. The order of steps is not guaranteed to match.

✗ Before
Teaprepare(): boil water steep tea leaves pour into cup add lemonCoffeeprepare(): boil water brew coffee grounds pour into cup add milk
Tea and Coffee each copy the whole recipe. A change to a shared step must be made twice.
Reach for it when
  • Several classes share the same overall flow but differ in some steps
  • You want to control the order in one place
  • Duplicate code sits in sibling classes
3

The idea

How the pattern fixes it.

Write the recipe once in a base class method (prepare) that calls step methods in a fixed order. Shared steps are written in the base; differing steps are abstract and filled in by each subclass.

✓ After
«abstract»Beverageprepare() ← fixed orderboil_water()pour()brew() ← fill inadd_extras() ← fill inTeabrew()add_extras()Coffeebrew()add_extras()
  • extends (is a)
The base class fixes the order of steps. Subclasses fill in only the steps that differ.

Who is who

Beverage (base)
prepare() is the template: boil, brew, pour, add extras.
brew(), add_extras()
Abstract steps each subclass must supply.
Tea, Coffee
Subclasses that fill the blanks.

Build it in steps

  1. 1Write the steps in order in one method.
  2. 2Move the shared steps into the base class.
  3. 3Declare the varying steps as abstract.
  4. 4Subclasses implement only those.
4

Watch it run

Step through the calls. Tap an arrow to jump to it.

ClientTea1prepare()2boil_water()3brew()4pour()5add_extras()6[4 steps]
Step 1/6

prepare() is the template. It lives in Beverage and runs the same steps for every drink.

prepare()
5

The code

Python and Java. Try writing the classes yourself from the diagram first.

class Beverage:
    def prepare(self):                               # the template method: fixed order
        return [self.boil_water(), self.brew(), self.pour(), self.add_extras()]

    def boil_water(self):
        return "boil water"

    def pour(self):
        return "pour into cup"

    def brew(self):                                  # steps the subclasses must fill in
        raise NotImplementedError

    def add_extras(self):
        raise NotImplementedError


class Tea(Beverage):
    def brew(self):
        return "steep tea leaves"

    def add_extras(self):
        return "add lemon"


class Coffee(Beverage):
    def brew(self):
        return "filter coffee"

    def add_extras(self):
        return "add milk"


def demo():
    return Tea().prepare(), Coffee().prepare()

What you gain

  • Duplicate code moves to one place
  • The order of steps is guaranteed

What it costs

  • Uses inheritance, so it is rigid
  • Many abstract steps make subclasses awkward

You have already met it in

  • JUnit's setUp / test / tearDown
  • Servlet doGet / doPost inside service()
  • Frameworks that call your hooks (Django views, React lifecycle)

Often mixed up with

  • StrategyTemplate Method changes steps by inheritance at compile time; Strategy swaps the whole algorithm by composition at run time.
  • Factory MethodA Factory Method is often one step inside a Template Method.
6

Make it stick

Write a DataExporter template: read(), transform(), write(). Make CsvExporter and JsonExporter override only the steps that differ.

Confidence