Behavioral

Template Method

Define the skeleton of an algorithm in a base class, deferring some steps to subclasses — subclasses can redefine certain steps without changing the algorithm's structure.

Beginner Pattern #22 of 23

What is the Template Method Pattern?

Template Method defines the overall structure of an algorithm in a base class method (the template method), and lets subclasses override specific steps without changing the skeleton. The base class controls the flow; subclasses provide the details.

This is the classic example of the Hollywood Principle: "Don't call us, we'll call you" — the base class calls the subclass methods, not the other way around.

Real-world analogy: Making a hot beverage. The template: boil water → brew → pour → add condiments. The brewing step differs (tea vs coffee), and condiments differ (milk vs lemon). The overall recipe (template) stays the same.

The Problem It Solves

You have a data mining application that processes reports from different formats (CSV, XML, PDF). Each format has different parsing and extracting logic, but the overall process is: open file → parse → extract data → analyse → send report. That pipeline is identical for all formats.

Without Template Method: duplicate the pipeline in every format class. With Template Method: put the pipeline in the base class, override only the format-specific steps in subclasses.

Participants

AbstractClass
Defines the template method — the algorithm skeleton as a series of method calls. Implements invariant parts. Declares abstract (required) and hook (optional override) methods for subclasses.
ConcreteClass
Implements the abstract steps. May override hook methods to extend or modify specific steps. Never overrides the template method itself.

Visual Flow Diagram

AbstractClass templateMethod() { ← FINAL step1() // concrete step2() // abstract (must override) hook() // optional override step3() // concrete } CSVDataMiner step2() — CSV parse hook() — override opt. XMLDataMiner step2() — XML parse hook() — not overridden ■ templateMethod = final ■ abstract = must override ■ hook = optional override (has default impl)

Java Code Example

Java — Data Mining Pipeline
// AbstractClass — defines the template
public abstract class DataMiner {

    // THE TEMPLATE METHOD — final: subclasses must NOT override
    public final void mine(String path) {
        String rawData  = openFile(path);         // concrete
        String data      = extractData(rawData);   // abstract — must override
        String parsed    = parseData(data);        // abstract — must override
        analyzeData(parsed);                      // concrete (shared logic)
        if (shouldSendReport()) {                 // hook — optional
            sendReport(parsed);                   // concrete
        }
        closeFile(path);                          // concrete
    }

    // Concrete steps — shared by all subclasses
    private String openFile(String path) {
        System.out.println("Opening: " + path);
        return "raw data from " + path;
    }
    private void analyzeData(String data) {
        System.out.println("Analyzing: " + data);
    }
    private void sendReport(String data) {
        System.out.println("Sending report for: " + data);
    }
    private void closeFile(String path) {
        System.out.println("Closing: " + path);
    }

    // Abstract steps — MUST be overridden by subclasses
    protected abstract String extractData(String raw);
    protected abstract String parseData(String data);

    // Hook — OPTIONAL override. Default: always send report
    protected boolean shouldSendReport() { return true; }
}

// ConcreteClass A — CSV format
public class CSVDataMiner extends DataMiner {
    protected String extractData(String raw) {
        System.out.println("Extracting CSV columns");
        return "csv_data";
    }
    protected String parseData(String data) {
        System.out.println("Parsing CSV rows");
        return "csv_parsed";
    }
    // does NOT override shouldSendReport — uses default (true)
}

// ConcreteClass B — XML format, overrides hook
public class XMLDataMiner extends DataMiner {
    private boolean debugMode;

    public XMLDataMiner(boolean debug) { this.debugMode = debug; }

    protected String extractData(String raw) {
        System.out.println("Extracting XML nodes");
        return "xml_data";
    }
    protected String parseData(String data) {
        System.out.println("Parsing XML elements");
        return "xml_parsed";
    }

    // Override hook — suppress report in debug mode
    protected boolean shouldSendReport() { return !debugMode; }
}

// Client — calls the template method
public class Main {
    public static void main(String[] args) {
        DataMiner csvMiner = new CSVDataMiner();
        csvMiner.mine("data.csv");       // runs full pipeline

        DataMiner xmlMiner = new XMLDataMiner(true);
        xmlMiner.mine("data.xml");       // skips report (debug mode)
    }
}

When to Use / Avoid

✓ Use When

  • Multiple classes share the same algorithm skeleton with only specific steps differing
  • You want to control which parts of the algorithm can be overridden
  • Duplicate code across subclasses can be pulled up into a shared template
  • Frameworks — base class controls the flow, plugins override specific steps

✕ Avoid When

  • Algorithm steps need to be combined in more flexible ways — use Strategy instead
  • The template method becomes huge with many abstract steps — hard to maintain
  • Liskov Substitution violations are common in subclasses — prefer composition

Real-World Examples

Pros & Cons

Pros

  • Eliminates code duplication — shared skeleton in one place
  • Controls the algorithm structure — subclasses can't break the flow
  • Hollywood Principle — base class orchestrates, subclasses provide details
  • Easy to add new variants — just extend and override specific steps

Cons

  • Liskov Substitution risk — subclasses can violate the contract of abstract steps
  • Hard to maintain as template methods grow with many abstract steps
  • Inheritance is less flexible than composition — hard to change hierarchy later

How Template Method Can Be Broken

⚠ Attack Vectors

  • Subclass overrides the template method: If the template method is not declared final, a subclass overrides the entire algorithm skeleton — the controlled structure is lost entirely
  • Abstract step throws instead of implementing: A ConcreteClass implements an abstract step by throwing UnsupportedOperationException — the base class template method crashes mid-run
  • Subclass calls base class steps directly: Subclass bypasses the template method and calls inherited concrete steps directly in a different order — violating the defined algorithm flow
  • Hook with side effects breaks flow: Overriding a hook with code that has unexpected side effects (e.g., modifying shared state) corrupts the template method's execution for other steps

✓ Prevention

  • Always declare template method final: public final void templateMethod() — makes it impossible for subclasses to override the skeleton, only the designated steps
  • Abstract steps must be meaningful: Document the contract of each abstract step clearly — what it must return, what side effects are allowed. Consider using an interface with a default method for hooks
  • Keep concrete steps private: Mark shared concrete steps as private — subclasses cannot call them out of order and the template retains full control
  • Hooks should be pure and minimal: Hook methods should have no side effects beyond what is documented — override hooks with only Boolean flags or simple customisations
Java — Break & Fix
// ❌ BREAKING — template method not final, subclass overrides it
public void mine(String path) { // ❌ not final
    /* skeleton */
}

public class RogueSubclass extends DataMiner {
    public void mine(String path) { // ❌ completely replaces the template!
        extractData(path);
        // skips analysis, skips close — template structure destroyed
    }
    protected String extractData(String r) { return ""; }
    protected String parseData(String d)   { return ""; }
}

// ✅ FIX — final template method cannot be overridden
public final void mine(String path) { // ✅ final — skeleton protected
    openFile(path); extractData(path); analyzeData(path); closeFile(path);
}

// ❌ BREAKING — abstract step throws instead of implementing
public class LazySubclass extends DataMiner {
    protected String extractData(String r) {
        throw new UnsupportedOperationException(); // ❌ base class crashes mid-run
    }
    protected String parseData(String d) { return ""; }
}

// ✅ FIX — abstract contract must be implemented properly
// Document with Javadoc what the method MUST do:
/**
 * Extracts raw fields from source data.
 * Must return non-null String. Never throw.
 */
protected abstract String extractData(String raw);

// ❌ BREAKING — concrete steps not private, subclass calls out of order
protected void openFile(String p) { /* ... */ } // ❌ protected — callable by subclass

public class BrokenSubclass extends DataMiner {
    protected String extractData(String r) {
        openFile("extra.csv"); // ❌ calling a step out of sequence
        return "";
    }
}

// ✅ FIX — concrete steps are private
private String openFile(String p) { return ""; } // ✅ subclass cannot call this

How Other Patterns Relate

Interview Cheat Sheet

  1. What: Base class defines algorithm skeleton as a final method calling abstract and hook methods. Subclasses provide implementations for abstract steps and optionally override hooks. Base class calls subclass — Hollywood Principle.
  2. Abstract vs Hook: Abstract step = subclass MUST implement (algorithm won't work without it). Hook = subclass MAY override (has a sensible default in the base class).
  3. Key distinction from Strategy: Template Method = inheritance, skeleton fixed. Strategy = composition, whole algorithm swapped. When you need runtime flexibility, prefer Strategy. When the skeleton is stable and shared, use Template Method.