Behavioral

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.”

Category: Behavioral Difficulty: Foundational Interview: Tier 2 Confused with: Strategy
01
Section One Β· The Problem

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.

Naive approach — duplicated algorithm structure
// βœ— Each parser repeats the same high-level steps class CsvReportMiner { public void mine(String path) { File file = openFile(path); // same for all String raw = extractCsvData(file); // CSV-specific Report data = parseCsv(raw); // CSV-specific Analysis a = analyze(data); // same for all generateSummary(a); // same for all closeFile(file); // same for all } } class XmlReportMiner { public void mine(String path) { File file = openFile(path); // same (duplicated) String raw = extractXmlData(file); // XML-specific Report data = parseXml(raw); // XML-specific Analysis a = analyze(data); // same (duplicated) generateSummary(a); // same (duplicated) closeFile(file); // same (duplicated) } } // Add PDF? Copy-paste entire mine() method, change 2 lines. 80% duplication.

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 skip analyze()
  • 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() and generateSummary() exist in multiple places; testing them means testing each parser individually
Without Template Method — duplicated algorithm in every subclass
CsvReportMiner mine(): openβ†’extractβ†’ parseβ†’analyzeβ†’close XmlReportMiner mine(): openβ†’extractβ†’ parseβ†’analyzeβ†’close PdfReportMiner mine(): openβ†’extractβ†’ parseβ†’analyzeβ†’close ✗ 80% of mine() is identical across all three classes ✗ Bug fix in analyze() must be applied to all parsers ✗ New step (e.g. logging) requires editing every class ✗ No enforcement of step order β€” easy to skip or reorder

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.

02
Section Two Β· The Pattern

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.

GoF Intent: “Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.”
— Gamma, Helm, Johnson, Vlissides (1994)
Analogy — building a house from a blueprint: A construction company has a standard blueprint for building houses. The blueprint defines the sequence: pour foundation, frame walls, install roof, run plumbing, run electrical, paint, and finish. Every house follows this exact order — you can’t install the roof before the walls. But the specifics of each step vary: one client wants brick walls, another wants timber; one wants a flat roof, another wants gabled; one wants copper plumbing, another wants PVC. The blueprint (template method) locks in the order and structure. The client’s choices (subclass overrides) customize the individual steps. The construction manager (base class) calls each step at the right time — the subcontractors (subclasses) just do their specific work when called.

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.

The base class defines templateMethod() as final — it calls steps in a fixed order
The algorithm structure is locked. No subclass can reorder steps, skip steps, or break the flow.
Variable steps are declared as abstract methods (or overridable hooks)
Subclasses must implement abstract steps and may override hooks. Each subclass provides its own variant without touching the skeleton.
Common steps (open file, close file, analyze) are implemented once in the base class
Zero duplication for shared logic. Fix a bug in analyze() once — all parsers inherit the fix.
Adding a new variant means creating a new subclass — not editing existing code
Open/Closed Principle: add a JsonReportMiner by overriding extractData() and parseData(). The base class is unchanged.
03
Section Three Β· Anatomy

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.
Template Method — UML Class Diagram
«abstract» ReportMiner + mine(path) : void Β«finalΒ» + openFile(path) : File + analyze(data) : Analysis + closeFile(file) : void # extractData(file) : String Β«abstractΒ» # parseData(raw) : Report Β«abstractΒ» mine() calls: 1. openFile() 2. extractData() ← abstract 3. parseData() ← abstract 4. analyze() 5. closeFile() CsvReportMiner # extractData(file) # parseData(raw) XmlReportMiner # extractData(file) # parseData(raw) PdfReportMiner # extractData(file) # parseData(raw) ■ Blue = abstract base class ■ Green = concrete subclass ■ Gold = template method (final) ▷ solid + hollow triangle = inheritance (extends) italic = abstract method (subclass must implement) mine() is final β€” subclasses override only extractData() and parseData()
Abstract steps vs. hooks:
  • 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.
04
Section Four Β· How It Works

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.

Step 1 — Client calls: ReportMiner miner = new CsvReportMiner(); miner.mine("sales.csv")
The mine() method is defined in ReportMiner (base class) as final. The client triggers the algorithm but cannot modify its structure.
Step 2mine() calls openFile("sales.csv") — a shared concrete step in the base class
File I/O logic runs identically for CSV, XML, and PDF. Implemented once in ReportMiner.
Step 3mine() calls extractData(file) — abstract, dispatches to CsvReportMiner
CsvReportMiner.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.
Step 4mine() calls parseData(raw) — abstract, dispatches to CsvReportMiner
CsvReportMiner.parseData() converts CSV rows into structured Report objects. The base class receives the result without knowing the parsing logic.
Step 5mine() calls analyze(data) and closeFile(file) — shared steps
Analysis and cleanup run the same way for all formats. If you add a logging step between analyze and close, you edit the base class once — all parsers get it.
Template Method — Execution Sequence (CSV miner)
Client ReportMiner (base class) CsvReportMiner mine("sales.csv") openFile() β€” shared extractData(file) Β«abstractΒ» β†’ reads CSV rows parseData(raw) Β«abstractΒ» β†’ builds Report objects analyze() β€” shared closeFile() β€” shared Blue steps = base class (shared). Green arrows = dispatched to subclass (variable). Client calls mine() once β€” base class drives the flow.
The pattern in pseudocode
// ── Client code ── ReportMiner miner = new CsvReportMiner(); miner.mine("sales.csv"); // ── Inside mine() β€” the template method ── // public final void mine(String path) // File f = openFile(path); ← shared // String r = extractData(f); ← abstract β†’ CsvReportMiner // Report d = parseData(r); ← abstract β†’ CsvReportMiner // Analysis a = analyze(d); ← shared // generateSummary(a); ← shared // closeFile(f); ← shared // // Output: // πŸ“‚ Opening file: sales.csv // πŸ“„ [CSV] Extracting comma-separated data... // πŸ”¨ [CSV] Parsing 142 rows into Report objects... // πŸ“Š Analyzing 142 records... // πŸ“‹ Summary: avg=$84.50, total=$12,000 // πŸ“‚ Closing file: sales.csv
Behavioral patterns need both static UML and dynamic sequence:
  • 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.
05
Section Five Β· Java Stdlib

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.

IN JAVA
Example 1 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.
Example 2 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.
Example 3 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.
Example 4 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.
Stdlib usage — custom list via AbstractList
// Override ONE method β†’ get 20+ operations for free class FixedList extends AbstractList<String> { private final String[] data; public FixedList(String... items) { this.data = items; } @Override public String get(int index) { return data[index]; } // ← abstract step @Override public int size() { return data.length; } // ← abstract step } // Now you get iterator(), contains(), indexOf(), subList()... List<String> list = new FixedList("A", "B", "C"); System.out.println(list.contains("B")); // true β€” uses get() internally System.out.println(list.indexOf("C")); // 2 β€” iterates via get()
Stdlib usage — custom InputStream
// Override read() β†’ base class builds read(byte[]), skip(), etc. class RepeatStream extends InputStream { private final byte value; public RepeatStream(byte value) { this.value = value; } @Override public int read() { return value; } // ← abstract step (one byte) } // Base class template method read(byte[], off, len) calls read() in a loop byte[] buf = new byte[4]; new RepeatStream((byte) 42).read(buf, 0, 4); // buf = [42, 42, 42, 42] β€” template method loops your read()
The “Abstract*” naming convention:
  • 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.
06
Section Six Β· Implementation

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.

Java — Template Method Data Miner (core)
// ── Abstract class with template method ── abstract class ReportMiner { // Template method β€” final: subclasses cannot change the order public final void mine(String path) { String raw = openAndRead(path); // shared List<String[]> rows = extractData(raw); // abstract List<Map<String,String>> records = parseData(rows); // abstract beforeAnalysis(records); // hook (optional) analyze(records); // shared close(path); // shared } // Shared concrete steps private String openAndRead(String p) { ... } private void analyze(List<...> r) { ... } private void close(String p) { ... } // Abstract steps β€” subclasses MUST implement protected abstract List<String[]> extractData(String raw); protected abstract List<Map<...>> parseData(List<String[]> rows); // Hook β€” default does nothing; subclasses CAN override protected void beforeAnalysis(List<...> r) { } }
Why 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 final guarantees the algorithm structure is immutable.
  • Subclasses customize what each step does, never when it runs.
07
Section Seven Β· Watch Out

Common Mistakes

Mistake #1 — Forgetting to make the template method 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.
✗ Wrong — template method is overridable
// βœ— Not final β€” a subclass can destroy the algorithm public void mine(String path) { // ← missing final! openFile(path); extractData(); parseData(); analyze(); closeFile(); } // A careless subclass overrides mine() and skips closeFile() class BadMiner extends ReportMiner { @Override public void mine(String path) { extractData(); // skips open, analyze, close β€” broken } }
✔ Correct — template method is final
// βœ“ final β€” no subclass can override the algorithm skeleton public final void mine(String path) { openFile(path); extractData(); parseData(); analyze(); closeFile(); }
Mistake #2 — Too many abstract steps (forcing subclasses to implement everything):
  • 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 abstract if every subclass must provide unique logic. Rule of thumb: 2-3 abstract steps max; the rest should be hooks or concrete methods.
Mistake #3 — Calling super in the wrong direction:
  • In Template Method, the base class calls the subclass (Hollywood Principle).
  • If a subclass calls super.extractData() inside its own extractData(), you’ve inverted the control flow and may trigger infinite recursion or duplicate logic.
  • Fix: Abstract steps should have no super call — they replace the step entirely. Only hooks should optionally call super to augment the default behavior.
Mistake #4 — Using Template Method when Strategy would be simpler:
  • 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.
Mistake #5 — Making shared steps protected instead of private:
  • If shared concrete steps like openFile() and analyze() are protected, 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 be protected (abstract steps and hooks).
08
Section Eight Β· Decision Guide

When To Use Template Method

Use Template Method When
  • 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
Avoid Template Method When
  • 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
Template Method vs. Confused Patterns
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
Decision Flowchart
Algorithm with multiple steps that vary? No Direct code Yes Fixed step order? Shared logic between variants? No Strategy (composition, runtime swap) Yes Need to swap variant at runtime? Yes Strategy + callbacks (inject step functions) No Template Method
09
Section Nine Β· Practice

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.
Interview Tip:
  • When asked about Template Method, the interviewer wants to see: (1) a final template 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 AbstractList and InputStream use this pattern in the JDK, and the tradeoff — Template Method creates coupling via inheritance, while Strategy uses composition (modern code often prefers Strategy + lambdas).