Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →The Template Method pattern puts an algorithm’s fixed sequence in one base-class method and delegates selected steps to subclasses. In Java, an abstract class usually contains that orchestration method, concrete invariant steps, abstract operations for required variation, and protected hooks for optional variation. Subclasses change those extension points without replacing the sequence.
What the Template Method pattern does
The pattern’s defining idea is to “define the skeleton of an algorithm in an operation, deferring some steps to subclasses.” The base class controls when each step runs; subclasses control selected details of how a step is performed.
For example, every report import might need to validate input, read records, transform them, and write output. The order is part of the import process. A CSV importer and an API importer can provide different reading or transformation code while following the same lifecycle.
Recognize the structure
The template method
This is the method that owns the algorithm’s sequence. It calls the steps in a deliberate order and is commonly public. Marking it final prevents subclasses from reordering, omitting, or inserting calls when that sequence is a contract.
Invariant operations
These steps are shared by every variant, so the base class implements them directly. They can be private or final methods when subclasses should not alter them.
Primitive operations
Primitive operations are required extension points. An abstract method communicates that every concrete subclass must provide an implementation. Use this for a step for which the base class has no sensible universal behavior.
Hooks
A hook is an overridable method with a default implementation, often an empty method or a default decision. Subclasses may override it, but they do not have to. Hooks are appropriate when most variants share the default behavior.
| Extension point | Base-class behavior | Subclass obligation | Typical use |
|---|---|---|---|
| Abstract primitive operation | No implementation | Must implement | Reading a source whose format differs for every importer |
| Concrete invariant operation | Shared implementation | Normally cannot change it | Validation rules common to all imports |
| Hook | Provides a default | May override | Optional logging, filtering, or notification |
A compact Java example
This example prepares reports. Validation and output formatting are fixed; loading and transforming data are required operations; an optional hook can add a header.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteRank #2
import java.util.List;
abstract class ReportJob {
// The algorithm skeleton: its order is the contract.
public final void run() {
validateInput();
List<String> records = readRecords();
List<String> transformed = transform(records);
addHeader(transformed); // optional hook
writeOutput(transformed);
}
private void validateInput() {
System.out.println("Input is valid");
}
protected abstract List<String> readRecords();
protected abstract List<String> transform(List<String> records);
protected void addHeader(List<String> records) {
// Default: no header.
}
private void writeOutput(List<String> records) {
records.forEach(System.out::println);
}
}
final class CsvReportJob extends ReportJob {
@Override
protected List<String> readRecords() {
return List.of("alice,42", "bob,37");
}
@Override
protected List<String> transform(List<String> records) {
return records.stream()
.map(row -> row.replace(',', ':'))
.toList();
}
@Override
protected void addHeader(List<String> records) {
records.add(0, "name:score");
}
}
Calling new CsvReportJob().run() always starts with validation, then reads, transforms, adds the optional header, and writes. The base-class call to readRecords(), transform(), and addHeader() uses normal Java dynamic dispatch, so the subclass implementations execute at runtime.
The sample uses List.of, which returns an unmodifiable list. If the hook must insert a header, return a mutable list from readRecords() or create one in transform(); otherwise the insertion will fail with UnsupportedOperationException. For example, return new ArrayList<>(List.of(...)) and import java.util.ArrayList.
Why make the template method final?
final is a design choice, not a requirement of the pattern. Use it when callers depend on the exact sequence—for example, validation must precede any I/O, or cleanup must always happen after processing. Leaving the method overridable can be reasonable when subclasses are intentionally allowed to extend or replace the workflow, but that weakens the guarantee that every variant follows the same algorithm.
Required operations versus hooks
Choose an abstract operation when omitting an implementation would make the algorithm incomplete or unsafe. The compiler then exposes an incomplete subclass immediately.
Recommended Free Tools
Choose a hook when a neutral default is valid. An empty hook is suitable for optional notifications; a boolean hook can supply a default policy:
protected boolean shouldPublish(List<String> records) {
return true;
}
Keep hooks narrow and document when they run, what state is available, and whether changing arguments is allowed. A hook that silently changes core invariants makes the base class difficult to reason about.
Java’s AbstractList as a skeletal-implementation example
Oracle’s Java SE 26 API documentation describes java.util.AbstractList<E> as a skeletal implementation that reduces the work required to implement List. For an unmodifiable list, a subclass supplies get(int) and size(). A modifiable, variable-size list additionally overrides set(int, E), add(int, E), and remove(int) as needed. The class supplies iterator and list-iterator behavior on top of the random-access operations.
This is best described as a practical skeletal implementation illustrating Template Method: shared operations are organized around behavior supplied by a subclass, even though the API documentation does not label AbstractList itself as “the Template Method pattern.”
Rank #4
When inheritance is a good fit
Before creating an abstract base class, evaluate the process and its variation:
- Stable sequence: The major steps and their order are expected to remain consistent.
- Clear variation points: Only a bounded set of steps differs between variants.
- Explicit obligations: You can identify which operations every subclass must implement and which have safe defaults.
- Acceptable coupling: Subclasses can depend on the base-class lifecycle and its protected API.
- Compile-time variants: The set of variants is represented by types rather than selected dynamically for each call.
Inheritance is a weaker fit when the sequence changes frequently, when clients must switch behavior at runtime, or when implementations need to combine several independent policies. In those cases, composition with strategy objects or injected functions usually keeps variation more independent from the workflow.
| Situation | Template Method assessment |
|---|---|
| One lifecycle, several fixed implementations | Strong fit |
| Most steps are shared; one or two are mandatory differences | Strong fit |
| Optional behavior is common but has a safe default | Good fit with hooks |
| Behavior must be swapped at runtime per request | Consider Strategy or composition |
| Subclasses need to reorder core steps | Usually a sign that the base sequence is not truly stable |
Common mistakes and how to avoid them
Making every step abstract
If all operations are abstract, the base class contributes little beyond a method call list. Implement genuinely invariant work in the base class and reserve abstract methods for real variation.
Allowing subclasses to bypass the lifecycle
An overridable template method lets a subclass skip validation or cleanup. Make it final, or clearly document which parts may be replaced.
Best Value
Using hooks for mandatory behavior
An empty default can hide a missing essential action. Make required work abstract so the compiler enforces it.
Exposing too much protected state
Protected fields and numerous hooks create a fragile subclass contract. Prefer small methods with explicit arguments and return values.
Changing the sequence without checking callers
Reordering steps can alter security checks, transactions, resource handling, and output. Treat the template method as an API contract and test the ordering directly.
Checklist for implementing the pattern
- Write the algorithm as an ordered list of steps.
- Mark each step invariant, required variation, or optional variation.
- Implement invariant steps in the base class.
- Declare required variations abstract.
- Give optional variations safe, documented hook defaults.
- Decide whether the template method should be
final. - Keep the subclass API small and test both the order and the extension-point behavior.
The Bottom Line
Use Template Method when one process has a stable sequence and a controlled set of subclass variations. Put that sequence in the base class, distinguish abstract required operations from default hooks, and protect the workflow with a final template method when order is part of the contract.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

