Template Method Pattern
Define the skeleton of an algorithm in a superclass, letting subclasses override specific steps without changing the overall structure. The foundation of framework design — Hollywood Principle: “Don’t call us, we’ll call you.”
Why Template Method Exists
You are building a data mining application that parses reports from different file formats — CSV, XML, and PDF. Each format requires different parsing logic, but the overall workflow is identical: open the file, extract raw data, parse it into a structured format, analyze the data, generate a summary, and close the file. The naive approach: each parser class duplicates the entire workflow.
What goes wrong:
- Massive duplication — the algorithm skeleton (
open β extract β parse β analyze β summarize β close) is copy-pasted in every parser; a bug fix in one must be replicated across all - No guaranteed structure — nothing enforces that a new parser follows the same step order; a developer might forget
closeFile()or skipanalyze() - Modification ripple — if you add a new step (e.g. logging before analysis), you must edit every parser class
- Untestable shared logic — common steps like
analyze()andgenerateSummary()exist in multiple places; testing them means testing each parser individually
This is the problem Template Method solves — define the algorithm’s skeleton once in a base class, and let subclasses override only the steps that vary. The invariant structure is locked in; the variant steps are deferred to subclasses.
What Is Template Method?
Template Method is a behavioral pattern that defines the skeleton of an algorithm in a base class method (the “template method”), deferring some steps to subclasses. Subclasses can override the variable steps without changing the algorithm’s overall structure or step order. The base class controls when each step runs; subclasses control how each step is implemented.
— Gamma, Helm, Johnson, Vlissides (1994)
Key insight: Template Method implements the Hollywood Principle: “Don’t call us, we’ll call you.” The base class calls the subclass methods at the right time — not the other way around. This is why every framework uses Template Method: Spring’s AbstractController, JUnit’s TestCase, Android’s Activity lifecycle — the framework controls the flow, you just fill in the steps. It’s inversion of control through inheritance.
templateMethod() as final — it calls steps in a fixed orderabstract methods (or overridable hooks)analyze() once — all parsers inherit the fix.JsonReportMiner by overriding extractData() and parseData(). The base class is unchanged.Participants & Structure
| Participant | Role | In the Analogy |
|---|---|---|
| Abstract Class (base class) | Defines the templateMethod() (usually final) that calls steps in order. Implements shared/invariant steps directly. Declares abstract methods for the variable steps that subclasses must provide. May declare hook methods with default no-op implementations that subclasses can override. | The construction blueprint — defines the build sequence and handles shared tasks (permits, inspections). |
| Concrete Class | Extends the abstract class and implements all abstract steps with format-specific logic. May optionally override hooks. Cannot change the template method itself (it’s final). | A specific builder — the brick mason, the timber framer, the roofer — each fills in their step of the blueprint. |
| Template Method (the method) | A final method in the abstract class that defines the algorithm skeleton. Calls abstract methods, concrete methods, and hooks in a fixed order. | The blueprint’s step-by-step sequence — pour foundation β frame walls β roof β plumbing β electrical β paint. |
| Abstract Steps | Declared abstract in the base class — subclasses must override. These are the variable parts of the algorithm. | Customizable choices: wall material, roof style, plumbing type. |
| Hooks | Optional methods with default (usually empty) implementations. Subclasses may override to inject behaviour at specific points without being forced to. | Optional upgrades: “want a skylight? Override the roof hook.” Default: no skylight. |
- An abstract step (
extractData()) has no implementation — every subclass must provide one. - A hook (
beforeAnalysis()) has a default empty implementation — subclasses may override it for optional behaviour. - Use abstract for mandatory variation; use hooks for optional extension points.
- Hooks are the “expansion slots” of your algorithm.
The Pattern In Motion
Scenario: A data mining pipeline processes a CSV sales report. The client calls miner.mine("sales.csv"). The template method in the abstract base class orchestrates the entire flow, calling subclass-specific steps at the right time.
ReportMiner miner = new CsvReportMiner(); miner.mine("sales.csv")mine() method is defined in ReportMiner (base class) as final. The client triggers the algorithm but cannot modify its structure.mine() calls openFile("sales.csv") — a shared concrete step in the base classReportMiner.mine() calls extractData(file) — abstract, dispatches to CsvReportMinerCsvReportMiner.extractData() reads comma-separated rows. An XmlReportMiner would parse XML tags instead. The base class doesn’t know the format — it just calls the method.mine() calls parseData(raw) — abstract, dispatches to CsvReportMinerCsvReportMiner.parseData() converts CSV rows into structured Report objects. The base class receives the result without knowing the parsing logic.mine() calls analyze(data) and closeFile(file) — shared steps- The UML (S03) shows who participates. The sequence diagram above shows who calls whom in what order.
- For Template Method, the key runtime insight is: the base class drives the flow, calling its own shared methods and dispatching abstract steps to the subclass via polymorphism.
- The subclass never calls
mine()or controls the order — the base class does.
You Already Use This
Template Method is the most prevalent pattern in the JDK’s collection framework and I/O system. Every time you extend an Abstract* class and override a few methods, you’re plugging into a template method that the base class controls.
java.util.AbstractList — the classic Template Method in Collections. It implements get(), indexOf(), iterator(), subList(), and more by calling the abstract method get(int index) that you must provide. Override one method, inherit 20+ operations. AbstractSet, AbstractMap, and AbstractQueue follow the same pattern. java.io.InputStream — defines the algorithm for reading bytes. You must override the single abstract method read() (reads one byte). The base class builds read(byte[] b), read(byte[] b, int off, int len), and skip() on top of your single-byte read(). OutputStream, Reader, and Writer follow the same structure. javax.servlet.http.HttpServlet — the service() method is the template method. It inspects the HTTP method (GET, POST, PUT, DELETE) and dispatches to doGet(), doPost(), etc. — which you override. The request lifecycle (parsing headers, routing, error handling) is locked in the base class. java.util.AbstractMap.SimpleEntry β and more broadly, every Abstract* class in the JDK. JUnit’s TestCase uses setUp()/tearDown() as hooks called by the framework’s test runner (template method). Spring’s JdbcTemplate is named after this pattern explicitly. - In the JDK, any class named
Abstract*(AbstractList,AbstractSet,AbstractQueue,AbstractMap) is almost certainly using Template Method. - The base class builds powerful operations on top of a few abstract methods you override.
- This is the “provide one, get many free” benefit of Template Method.
Build It Once
Domain: Data Mining Pipeline. A ReportMiner abstract class defines the template method mine() with shared steps and abstract extraction/parsing methods. Concrete subclasses (CsvReportMiner, XmlReportMiner) provide format-specific logic.
mine() is final: - If subclasses could override
mine(), they could change the step order, skip steps, or call them in the wrong sequence — defeating the entire purpose of Template Method. - Making the template method
finalguarantees the algorithm structure is immutable. - Subclasses customize what each step does, never when it runs.
Common Mistakes
final: If mine() is not final, a subclass can override it entirely — reordering steps, skipping shared logic, or breaking the algorithm. The whole point of Template Method is that the structure is locked. Fix: Always declare the template method as final. In Python (no final keyword), document the contract clearly and raise NotImplementedError if someone tries to override the wrong method.
- If the base class has 8 abstract methods, every subclass must override all 8 — even if most would use default logic.
- This turns Template Method into a burden.
- Fix: Use hooks (methods with default empty implementations) for optional steps. Only make a step
abstractif every subclass must provide unique logic. Rule of thumb: 2-3 abstract steps max; the rest should be hooks or concrete methods.
super in the wrong direction: - In Template Method, the base class calls the subclass (Hollywood Principle).
- If a subclass calls
super.extractData()inside its ownextractData(), you’ve inverted the control flow and may trigger infinite recursion or duplicate logic. - Fix: Abstract steps should have no
supercall — they replace the step entirely. Only hooks should optionally callsuperto augment the default behavior.
- Template Method uses inheritance β each variant is a subclass.
- If you have many variants and the algorithm is simple, you end up with a class explosion.
- Fix: If the variant behavior is a single step (e.g. “how to sort”), use Strategy (pass a function/interface). Use Template Method only when the algorithm has multiple steps with a fixed order and shared logic between steps.
protected instead of private: - If shared concrete steps like
openFile()andanalyze()areprotected, subclasses can override them — defeating the “invariant” guarantee. - Fix: Shared steps that should never change must be
private. Only steps intended for subclass customization should beprotected(abstract steps and hooks).
When To Use Template Method
- Multiple classes share the same algorithm structure but differ in specific steps — e.g. data parsers, test frameworks, build pipelines
- You want to enforce a fixed step order — steps must run in sequence, and subclasses should not be able to reorder or skip them
- There is significant shared logic between variants — the invariant parts should live in one place, not be copy-pasted
- You are building a framework — you control the lifecycle; users fill in the blanks (Hollywood Principle)
- You need optional extension points — hooks let subclasses inject behaviour at specific points without forcing them to implement every step
- The variant behaviour is a single step (not a multi-step algorithm) — use Strategy instead; it’s simpler and avoids inheritance
- You need to swap behaviour at runtime — Template Method uses inheritance (compile-time); Strategy uses composition (runtime swappable)
- There are many variants and each differs in only one line — creating a new subclass per variant is overkill; use a lambda/Strategy
- The algorithm has no invariant structure — if every step varies and there’s no shared logic, there’s nothing to template
| Pattern | Mechanism | Varies What? | When to pick it |
|---|---|---|---|
| Template Method ← this | Inheritance (extends) | Steps within a fixed algorithm | Multi-step algorithm with shared structure and invariant order |
| Strategy | Composition (interface + inject) | Entire algorithm | Swap one behaviour at runtime; single-step variation |
| Factory Method | Inheritance (extends) | Which object to create | A step in the algorithm creates a product; subclass decides which product |
| Builder | Composition (step-by-step) | Complex object construction | Object has many optional parts; construct fluently |
Problems To Solve
Template Method problems test whether you can identify the invariant algorithm structure, separate fixed steps from variable steps, and correctly use abstract methods vs. hooks.
| Difficulty | Problem | Key Insight |
|---|---|---|
| Easy | Beverage Maker Build a BeverageMaker base class with the template method prepare(): boil water β brew β pour β add condiments. TeaMaker steeps tea leaves and adds lemon. CoffeeMaker drips coffee grounds and adds sugar + milk. The “add condiments” step is a hook — some drinks skip it. | Tests the basic structure: final template method, two abstract steps (brew() and addCondiments()), two shared steps (boilWater() and pour()). The hook variant: make addCondiments() a hook with a default no-op so a PlainWaterMaker subclass works without overriding it. |
| Medium | Game AI Turn Build a GameAI base class with takeTurn(): collect resources β build structures β train units β attack. OrcsAI collects gold, builds barracks, trains grunts, attacks nearest enemy. MonstersAI skips building entirely (hook returns false). Add a shouldBuild() hook that controls whether the build step runs. | Tests hooks as conditional gates. The template method checks if (shouldBuild()) buildStructures(). Default hook returns true; MonstersAI overrides it to return false. This demonstrates hooks as control points — not just “extra logic” but “conditionals that subclasses can flip.” |
| Medium | Unit Test Framework Build a mini test framework inspired by JUnit. Base class TestCase has run(): setUp() β runTest() β tearDown(). setUp() and tearDown() are hooks (default no-op). runTest() is abstract. Each test class extends TestCase and overrides runTest(). Add a hook beforeEach() that runs before every test. | Tests a real-world Template Method (JUnit’s actual design). The framework controls the lifecycle; user tests fill in runTest(). The interesting part: setUp() and tearDown() are hooks, not abstract — most tests don’t need them, but some override for setup/cleanup. This is exactly how @BeforeEach and @AfterEach work. |
| Hard | ETL Pipeline Framework Build an ETL (Extract-Transform-Load) framework using Template Method. The base ETLPipeline has run(): connect β extract β validate β transform β load β disconnect. Validation is a hook that defaults to accepting all records. Add a beforeLoad() hook for batching. Implement DatabaseToCSV and APIToDatabase pipelines. Handle errors: if transform() fails, disconnect() must still run (try/finally in the template method). | Tests Template Method at production scale. The template method uses try/finally to guarantee disconnect() runs even on failure — this is why frameworks use this pattern (resource lifecycle management). The validation hook demonstrates optional filtering. The beforeLoad() hook demonstrates batching. Two concrete pipelines show different sources/targets but identical lifecycle. |
- When asked about Template Method, the interviewer wants to see: (1) a
finaltemplate method in the base class that defines the algorithm skeleton; (2) abstract steps for mandatory variation; (3) hooks for optional extension; (4) shared/invariant logic implemented once in the base class. - Stand-out answers mention: the Hollywood Principle (“don’t call us, we’ll call you”), the difference from Strategy (inheritance vs. composition, compile-time vs. runtime), how
AbstractListandInputStreamuse this pattern in the JDK, and the tradeoff — Template Method creates coupling via inheritance, while Strategy uses composition (modern code often prefers Strategy + lambdas).