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 couplingPremium Content
Unlock Template Method and all premium lessons with a subscription.
From ₹199.99/year — See plans