Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • About
  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

👥10,050visitors

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
HomeLearnSystem DesignLow-Level Design & Design PatternsBehavioral Design Patterns
✓ FreeBeginner· 8 min read

Template Method

Defining an algorithm's fixed skeleton in a base class while deferring individual steps to subclasses — via a read-validate-transform-save DataProcessor.

Published September 23, 2026


Template Method

The idea: fix the sequence, let subclasses fill in the steps

Some algorithms have a sequence of steps that should always happen in the same order, but where individual steps vary by context. Template Method puts the fixed sequence in a base class method (the "template"), marked final so subclasses can't reorder it, while individual steps are abstract (or have a default, overridable implementation) for subclasses to customize.

abstract class DataProcessor {
    // the template — fixed sequence, cannot be reordered or skipped by subclasses
    public final void process() {
        List<String> raw = read();
        List<String> valid = validate(raw);
        List<String> transformed = transform(valid);
        save(transformed);
    }

    protected abstract List<String> read();
    protected abstract List<String> validate(List<String> raw);
    protected abstract List<String> transform(List<String> valid);
    protected abstract void save(List<String> data);
}

class CsvDataProcessor extends DataProcessor {
    protected List<String> read() { return readCsvFile(); }
    protected List<String> validate(List<String> raw) { return raw.stream().filter(this::isValidRow).toList(); }
    protected List<String> transform(List<String> valid) { return valid.stream().map(this::normalize).toList(); }
    protected void save(List<String> data) { writeToDatabase(data); }
    // helper methods omitted
}

class JsonDataProcessor extends DataProcessor {
    protected List<String> read() { return readJsonFile(); }
    protected List<String> validate(List<String> raw) { return raw.stream().filter(this::isValidJson).toList(); }
    protected List<String> transform(List<String> valid) { return valid.stream().map(this::flatten).toList(); }
    protected void save(List<String> data) { writeToBlobStorage(data); }
}
DataProcessor csv = new CsvDataProcessor();
csv.process(); // always read -> validate -> transform -> save, in that exact order, guaranteed

Every subclass gets the same guaranteed sequence — you can't accidentally call save() before validate() from within a subclass, because subclasses never call process()'s steps directly; they only ever implement individual steps that the (unoverridable, final) template calls in the fixed order.

Advertisement

Template Method vs Strategy — inheritance vs composition

Both let you vary behavior, but through opposite mechanisms: Template Method customizes individual steps of an algorithm via inheritance (a subclass overrides specific abstract methods, but the overall structure lives in the base class and can't be swapped as a whole). Strategy swaps the entire algorithm via composition (a completely different PricingStrategy object can be substituted, with no shared base-class structure constraining it at all). Template Method fits when the steps' order must stay fixed and only how each step works varies; Strategy fits when the whole algorithm might be replaced wholesale, with no assumption that it shares any structure with the alternative.

A fuller example: hooks, invariants and failure handling

The core idea is simple: a base class fixes an algorithm's skeleton, and subclasses fill in steps. What makes it valuable in real code is that the base class can guarantee things every variant must do, such as validation, timing, cleanup and error handling, so individual subclasses can't forget them.

public abstract class ReportGenerator {

    /** The template method: final, so the sequence and its guarantees can't be bypassed. */
    public final Report generate(ReportRequest request) {
        validate(request);                                   // invariant step, same for all reports
        Instant start = Instant.now();
        try (DataCursor data = openData(request)) {          // resource ALWAYS closed
            List<Row> rows = new ArrayList<>();
            while (data.hasNext()) {
                Row row = data.next();
                if (include(row)) rows.add(transform(row));  // hook + abstract step
            }
            Report report = render(request, rows);           // abstract step
            afterRender(report);                             // optional hook
            return report;
        } catch (IOException e) {
            throw new ReportFailedException(getClass().getSimpleName(), e);   // uniform error type
        } finally {
            metrics.record(getClass().getSimpleName(), Duration.between(start, Instant.now()));
        }
    }

    // --- steps subclasses MUST provide ---
    protected abstract DataCursor openData(ReportRequest request) throws IOException;
    protected abstract Report render(ReportRequest request, List<Row> rows);

    // --- hooks subclasses MAY override (sensible defaults) ---
    protected boolean include(Row row) { return true; }
    protected Row transform(Row row) { return row; }
    protected void afterRender(Report report) {}

    // --- private: not overridable at all ---
    private void validate(ReportRequest r) {
        if (r.from().isAfter(r.to())) throw new IllegalArgumentException("from must be before to");
    }
}

public class MonthlySalesReport extends ReportGenerator {
    @Override protected DataCursor openData(ReportRequest r) { return salesRepo.cursor(r.from(), r.to()); }
    @Override protected boolean include(Row row) { return !row.getBoolean("test_order"); }   // hook used
    @Override protected Report render(ReportRequest r, List<Row> rows) { return new CsvReport(rows); }
}

Three kinds of methods, and each choice is deliberate:

KindModifierPurpose
Template methodpublic finalThe fixed sequence. Can't be overridden, so its guarantees hold
Abstract stepsprotected abstractThe parts that genuinely differ. The compiler forces subclasses to supply them
Hooksprotected with a defaultOptional customization points. Most subclasses ignore them
Invariant helpersprivateSteps no subclass should change

The guarantees are the point. Every report is validated, closes its data cursor even on failure, records timing metrics, and reports errors the same way, without any subclass having to remember to.

Template Method in the frameworks you already use

  • Spring's JdbcTemplate, RestTemplate and TransactionTemplate: the "template" in their names is this idea, though implemented with callbacks instead of inheritance. JdbcTemplate handles getting a connection, creating the statement, translating exceptions and closing resources. You supply only the SQL and a RowMapper.
  • AbstractList, AbstractMap in the JDK: implement get and size, and you inherit dozens of methods built on top of them.
  • JUnit's lifecycle: @BeforeEach → test → @AfterEach is a fixed sequence with hooks.
  • Servlet HttpServlet.service() dispatches to doGet/doPost, which you override.

The callback alternative

Inheritance ties each variant to one base class, and Java allows only one. The same skeleton can be written with functions passed in (composition), which is why modern APIs often prefer it:

public <T> T inTransaction(Function<Connection, T> work) {
    try (Connection c = dataSource.getConnection()) {
        c.setAutoCommit(false);
        try { T result = work.apply(c); c.commit(); return result; }
        catch (RuntimeException e) { c.rollback(); throw e; }
    } catch (SQLException e) { throw new DataAccessException(e); }
}

Order saved = inTransaction(conn -> orderDao.insert(conn, order));

Use a Template Method class hierarchy when there are several steps and hooks, and a natural "is-a" relationship. Use callbacks when there are one or two varying steps, or when the variants shouldn't have to extend a particular base class.

Follow-up questions this topic invites — and their answers

Q: Why mark the template method final? A: To enforce the entire point of the pattern — if subclasses could override process() itself, they could reorder or skip steps, which defeats the guarantee that the sequence is fixed. final makes that guarantee a compile-time fact, not a convention subclasses are trusted to follow.

Q: Can a step have a default implementation instead of being purely abstract? A: Yes — a "hook" method with a default (often no-op) implementation lets subclasses optionally override just the steps they care about, while inheriting sensible defaults for the rest. This is common when most steps are usually the same across subclasses and only one or two genuinely vary.

Q: Isn't this just normal inheritance and method overriding — what makes it a distinct 'pattern'? A: The pattern-worthy part isn't overriding itself, it's the specific structure: a final (or otherwise protected-from-override) method that calls several abstract/hook methods in a fixed sequence. That structural commitment — 'the algorithm's shape is fixed, only its steps vary' — is what distinguishes Template Method from arbitrary polymorphism.

Q: How would you test a subclass's individual step in isolation, without running the whole template sequence? A: Since each step is its own protected method, you can test it directly if you expose it at package-visibility or via a test subclass — though testing through process() end-to-end is usually more valuable, since the steps are specifically meant to be evaluated as part of the fixed sequence, not independently.

Q: What's a "hook" in Template Method, and how is it different from an abstract step? A: An abstract step must be implemented by every subclass, because the algorithm can't work without it. A hook has a default implementation (often doing nothing), and subclasses override it only when they need to customize that point.

Q: How is Spring's JdbcTemplate related to the Template Method pattern? A: It applies the same idea (a fixed skeleton of acquiring a connection, executing, mapping, translating exceptions and releasing resources) but supplies the varying parts through callbacks such as RowMapper, rather than through subclassing. That's the composition-based variant of Template Method.

Q: What's the main risk of Template Method? A: Fragile base classes. Subclasses depend on the exact order and behaviour of the skeleton, so changes to the base class can break them in subtle ways. Keep the template small, document the contract of each step, and prefer callbacks when variants are few.

Advertisement

Previous

Command Pattern

Next

State Pattern

AI Tutor

Lesson: Template Method

Quick actions

AI responses can be inaccurate. Verify critical information.