Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Template Method
LLD

Template Method

Learn how to define an algorithm skeleton while allowing subclasses to customize selected steps.

Template Method: Algorithm Skeleton

The Template Method pattern is best understood as a way to control the shape of an algorithm without controlling every detail of its implementation.

It is useful when several workflows follow the same sequence of steps, but some steps vary between implementations.

The central idea is:

               ALGORITHM SKELETON
                      |
                      v
        +-----------------------------+
        | step 1                      |
        | step 2                      |
        | customizable step           |
        | step 4                      |
        | customizable step           |
        +-----------------------------+
                      |
              fixed by base class
                      |
          +-----------+-----------+
          |                       |
          v                       v
    ConcreteA                ConcreteB
       |                         |
       +-- custom step           +-- custom step

The important distinction is:

The base class owns the algorithm’s control flow; subclasses provide selected pieces of behavior.


1. The Engineering Problem

Suppose several systems process data:

Load data

Validate data

Transform data

Save result

For one implementation:

CSV
  load CSV
  validate
  transform
  save

For another:

JSON
  load JSON
  validate
  transform
  save

A naive implementation might duplicate the workflow:

class CsvProcessor {
    void process() {
        load();
        validate();
        transform();
        save();
    }
}
class JsonProcessor {
    void process() {
        load();
        validate();
        transform();
        save();
    }
}

The problem isn’t that the code doesn’t work.

The problem is the algorithm’s structure is duplicated.

Eventually one implementation changes:

load
validate
transform
save

to:

load
validate
transform
audit
save

Now every implementation has to be updated.

That is where Template Method becomes useful.


2. The Core Design

Move the invariant workflow into a base class:

abstract class DataProcessor {

    public final void process() {
        load();
        validate();
        transform();
        save();
    }

    protected abstract void load();

    protected abstract void transform();

    protected void validate() {
        // default behavior
    }

    protected abstract void save();
}

Then subclasses implement only the variable parts:

class CsvProcessor extends DataProcessor {

    @Override
    protected void load() {
        // Load CSV
    }

    @Override
    protected void transform() {
        // Transform CSV
    }

    @Override
    protected void save() {
        // Save CSV result
    }
}
class JsonProcessor extends DataProcessor {

    @Override
    protected void load() {
        // Load JSON
    }

    @Override
    protected void transform() {
        // Transform JSON
    }

    @Override
    protected void save() {
        // Save JSON result
    }
}

The client only sees:

processor.process();

The workflow cannot be reordered by the subclass.


3. The Key Insight: Inversion of Control

This is the most important concept behind Template Method.

Normally, application code might control the sequence:

Client
  |
  +--> load()
  +--> validate()
  +--> transform()
  +--> save()

With Template Method:

Client
  |
  | process()
  v
Base Class
  |
  +--> load()       ---> subclass
  |
  +--> validate()   ---> base/default
  |
  +--> transform()  ---> subclass
  |
  +--> save()       ---> subclass

The base class controls when operations happen.

The subclass controls how selected operations happen.

This is a form of inversion of control.

A useful way to phrase it:

The superclass calls the subclass, not the other way around.


4. UML Class Diagram

                 <<abstract>>
                 DataProcessor
        +-----------------------------+
        | + process()                 |
        |-----------------------------|
        | # load()                    |
        | # validate()                |
        | # transform()               |
        | # save()                    |
        +-------------+---------------+
                      ^
                      |
              +-------+-------+
              |               |
      +-------+------+ +------+-------+
      | CsvProcessor | | JsonProcessor|
      +--------------+ +--------------+
      | # load()     | | # load()     |
      | # transform()| | # transform()|
      | # save()     | | # save()     |
      +--------------+ +--------------+

The crucial point is that:

process()

belongs to the base class.

The subclasses do not define the workflow.


5. The Template Method

The method containing the algorithm skeleton is called the Template Method.

For example:

public final void process() {
    load();
    validate();
    transform();
    save();
}

It is often declared:

final

when the framework designer wants to guarantee that subclasses cannot alter the algorithm.

This is an important design decision.

Without final:

class BadProcessor extends DataProcessor {

    @Override
    public void process() {
        save();
        load();
    }
}

The subclass can violate the algorithm’s invariants.

With:

public final void process()

the algorithm structure is protected.


6. Primitive Operations

The methods called by the Template Method are often called primitive operations or hook points.

For example:

process()
   |
   +-- load()       <- primitive operation
   +-- validate()   <- hook/default
   +-- transform()  <- primitive operation
   +-- save()       <- primitive operation

There are usually two kinds.

Abstract operation

The subclass must implement it.

protected abstract void load();

Hook

The base class provides default behavior, but subclasses may override it.

protected void validate() {
    // Default: do nothing
}

This distinction is fundamental.


7. Hooks

A hook is an optional customization point.

Example:

abstract class ReportGenerator {

    public final void generate() {
        loadData();
        beforeRender();
        render();
        afterRender();
    }

    protected abstract void loadData();

    protected abstract void render();

    protected void beforeRender() {
        // optional
    }

    protected void afterRender() {
        // optional
    }
}

A subclass can override:

protected void beforeRender() {
    authenticate();
}

but doesn’t have to.

This allows the base class to provide sensible defaults.


8. Sequence Diagram

Consider:

processor.process();

Runtime behavior:

Client          DataProcessor       CsvProcessor
  |                  |                   |
  | process()        |                   |
  |----------------->|                   |
  |                  |                   |
  |                  | load()            |
  |                  |------------------>|
  |                  |                   |
  |                  |<------------------|
  |                  |                   |
  |                  | validate()        |
  |                  |------------------>|
  |                  |                   |
  |                  |<------------------|
  |                  |                   |
  |                  | transform()       |
  |                  |------------------>|
  |                  |                   |
  |                  |<------------------|
  |                  |                   |
  |                  | save()            |
  |                  |------------------>|
  |                  |                   |
  |                  |<------------------|
  |<-----------------|                   |

The important observation:

Client
  |
  v
process()
  |
  v
Base class controls sequence
  |
  +--> subclass implementation

9. Why This Is Different From Ordinary Inheritance

Inheritance alone isn’t the pattern.

This:

class Dog extends Animal {
}

is not Template Method.

Template Method requires:

Base class
   |
   +-- defines algorithm
   |
   +-- delegates variable steps
            |
            v
       subclass methods

The defining characteristic is:

A superclass method defines the invariant algorithm and calls overridable operations at specific points.


10. Template Method vs Strategy

This is one of the most important comparisons.

Template Method

Uses:

Inheritance
           Algorithm
              |
      +-------+-------+
      |               |
   CSV impl        JSON impl

The variation is supplied by subclasses.

Strategy

Uses:

Composition
             Processor
                 |
                 v
              Strategy
             /        \
      CsvStrategy   JsonStrategy

Strategy is generally more flexible because behavior can be changed at runtime.

Template Method is more appropriate when:

  • the overall algorithm is fundamentally fixed;
  • implementations are naturally variants of the same abstraction;
  • inheritance is already a good domain relationship.

A useful rule:

Template Method varies parts of an inherited algorithm; Strategy replaces an algorithm through composition.


11. Template Method vs Factory Method

These patterns are frequently confused because they often appear together.

Template Method:

Controls an algorithm

Factory Method:

Controls creation of an object

They can be combined.

For example:

abstract class ReportService {

    public final void generate() {
        Report report = createReport();
        populate(report);
        save(report);
    }

    protected abstract Report createReport();

    protected abstract void populate(Report report);

    protected void save(Report report) {
        // default implementation
    }
}

Here:

generate()

is Template Method.

createReport()

is Factory Method.


12. Template Method vs Visitor

Visitor:

Adds operations to a stable object structure.

Template Method:

Defines an algorithm with customizable steps.

Think:

Visitor
    "What operation should I perform?"

Template Method
    "What sequence of steps must happen?"

Visitor is about operation extensibility.

Template Method is about algorithm structure and controlled variation.


13. Real Example: Authentication

Imagine authentication workflows:

Receive credentials

Validate request

Load user

Verify credentials

Create session

Audit login

The workflow should remain consistent.

But credential verification may differ:

Password
OAuth
Certificate
API Key

A Template Method could look like:

abstract class AuthenticationFlow {

    public final void authenticate(Request request) {
        validateRequest(request);
        User user = loadUser(request);
        verifyCredentials(request, user);
        createSession(user);
        audit(user);
    }

    protected void validateRequest(Request request) {
        // common validation
    }

    protected abstract User loadUser(Request request);

    protected abstract void verifyCredentials(
        Request request,
        User user
    );

    protected void createSession(User user) {
        // common behavior
    }

    protected void audit(User user) {
        // common behavior
    }
}

The security-critical sequence remains centralized.


14. Why final Can Matter in Framework Design

Consider:

public void execute() {
    authenticate();
    authorize();
    executeBusinessLogic();
    audit();
}

If subclasses can override execute():

@Override
public void execute() {
    executeBusinessLogic();
}

they can accidentally bypass:

authentication
authorization
audit

That can be a serious architectural problem.

Therefore, framework-level Template Methods are often:

public final void execute()

while extension points are:

protected abstract ...
protected ...

This creates:

                 Framework
                    |
          +---------+---------+
          |                   |
      Fixed flow          Extension points
          |                   |
       final             protected

This is a powerful technique for enforcing invariants.


15. The Hollywood Principle

Template Method is strongly related to the Hollywood Principle:

“Don’t call us, we’ll call you.”

The framework/base class controls execution:

Base class
    |
    +--> calls subclass hook
    +--> calls subclass operation

Instead of the subclass controlling the framework:

Subclass
    |
    +--> manually invokes framework steps

This prevents clients/subclasses from deciding the ordering of critical operations.


16. Where Template Method Works Particularly Well

Frameworks

A framework may define:

initialize
validate
execute
cleanup

while allowing applications to customize individual stages.

Data processing

read
parse
validate
transform
persist

ETL pipelines

extract
validate
transform
load

Build systems

prepare
compile
test
package

Request processing

authenticate
authorize
process
audit

Testing infrastructure

setup
execute
verify
teardown

Batch processing

initialize
process records
finalize

17. Advantages

Consistent algorithm

The workflow is defined once.

Avoids duplication

Common orchestration lives in one place.

Controlled extension

Subclasses can customize specific steps.

Enforces invariants

A final Template Method can prevent invalid workflows.

Good framework mechanism

Frameworks can define lifecycle rules while applications provide implementation details.


18. Disadvantages

Inheritance coupling

The subclass is tightly coupled to the base class.

ConcreteClass
      |
      v
BaseClass

Changes to the base class can affect every subclass.

Fragile base class problem

Changing:

process()

can unexpectedly break subclasses that rely on its behavior.

Harder composition

Behavior is determined by the class hierarchy rather than being freely composed.

Hook complexity

Too many hooks can create an unclear lifecycle:

beforeA()
afterA()
beforeB()
afterB()
...

Subclass explosion

If variation occurs along many independent dimensions, inheritance can become unwieldy.


19. The Fragile Base Class Problem

This deserves special attention.

Suppose the original template is:

process() {
    load();
    transform();
    save();
}

Later someone changes it:

process() {
    load();
    validate();
    transform();
    save();
}

An old subclass might implicitly depend on:

load()
→ transform()

and behave incorrectly when validate() is introduced.

This is one reason Template Method should be designed carefully in public APIs and frameworks.


20. Template Method and the Liskov Substitution Principle

A subclass must still behave correctly wherever the base abstraction is expected.

If the base class promises:

authenticate
→ authorize
→ execute
→ audit

a subclass shouldn’t secretly violate those guarantees.

This is another reason the fixed algorithm often belongs in a final method.

The base class defines the contract:

process()

while subclasses provide implementations of permitted extension points.


21. A Principal-Engineer Design Question

Don’t ask:

“Can I use Template Method here?”

Ask:

“Which parts of this workflow are invariant, and which parts are legitimate extension points?”

For example:

           Processing Workflow

        +-----------------------+
        | validate              | ← invariant
        +-----------------------+
                  |
        +-----------------------+
        | load                  | ← variable
        +-----------------------+
                  |
        +-----------------------+
        | transform             | ← variable
        +-----------------------+
                  |
        +-----------------------+
        | audit                 | ← invariant
        +-----------------------+
                  |
        +-----------------------+
        | persist               | ← variable
        +-----------------------+

The Template Method should own the invariant structure.

The subclasses should only control legitimate variation.


22. When Template Method Is the Wrong Abstraction

Suppose you have:

Compression
Encryption
Serialization
Notification
Caching

and each can vary independently.

Inheritance starts producing combinations:

CompressedEncryptedProcessor
CompressedCachedProcessor
EncryptedCachedProcessor
CompressedEncryptedCachedProcessor
...

This is a sign that composition is probably better.

Use:

Strategy
Decorator
Pipeline
Composition

depending on the problem.

A good rule:

If you have multiple independent axes of variation, inheritance-based Template Method often becomes brittle.


23. Template Method and Modern Design

Classic GoF Template Method is based on inheritance.

Modern systems often prefer:

Composition
Dependency Injection
Strategy
Pipelines
Higher-order functions
Callbacks

because they reduce inheritance coupling.

That doesn’t make Template Method obsolete.

It means you should use it where the algorithm itself is part of the abstraction.

For example:

Framework lifecycle
Security workflow
Transaction lifecycle
Compiler pass lifecycle
Test lifecycle

These are strong candidates because the ordering itself is meaningful.


24. Template Method Through a Change-Analysis Lens

This is perhaps the most useful way to decide whether to use it.

Suppose you have:

             ALGORITHM
                 |
       +---------+---------+
       |                   |
   Invariant             Variable
       |                   |
       v                   v
   Base class           Subclass

If this boundary is stable, Template Method works well.

If the boundary constantly changes:

Step A sometimes exists
Step B moves around
Step C becomes optional
Step D changes ordering

then Template Method may become a poor abstraction.

The pattern works best when the algorithm skeleton itself is stable.


25. A More Complete UML

                         <<abstract>>
                        DataProcessor
                 +-------------------------+
                 |                         |
                 | + final process()       |
                 |                         |
                 | # abstract load()      |
                 | # validate()           |
                 | # abstract transform() |
                 | # abstract save()      |
                 | # hook beforeSave()    |
                 +-----------+-------------+
                             ^
                             |
                 inheritance |
                  +----------+----------+
                  |                     |
          +-------+-------+     +-------+-------+
          | CsvProcessor  |     | JsonProcessor |
          +---------------+     +---------------+
          | load()        |     | load()        |
          | transform()   |     | transform()   |
          | save()        |     | save()        |
          +---------------+     +---------------+

The architecture can be summarized as:

                    BASE CLASS
                       |
                       v
                +-------------+
                | Algorithm   |
                |  skeleton   |
                +------+------+
                       |
             +---------+---------+
             |         |         |
             v         v         v
           Hook      Hook      Hook
             |         |         |
             v         v         v
        Subclass implementations

26. Template Method in One Sentence

Template Method defines the invariant skeleton of an algorithm in a base class and delegates selected steps to subclasses or hooks.


27. The Decision Rule

Use Template Method when:

Same workflow
     +
Same ordering
     +
Some steps vary
     +
Inheritance is acceptable
     =
Template Method

Prefer Strategy/composition when:

Algorithms vary substantially
     OR
Variation is independent
     OR
Runtime replacement is needed
     OR
Inheritance creates coupling

My Private Notes

Notes are auto-saved locally to this device.