Reach for it when three or four jobs march in the same order and differ in only one or two spots. Instead of copying the order into every class, write it down once. In an interview, the moment you spot "same steps, same order, one part varies," this is the pattern that earns points for seeing structure instead of listing classes.
If you remember five things
The whole pattern in one glance. Everything below defends these five.
- Intent. A parent owns the algorithm's skeleton (the step order), and subclasses override only the steps that genuinely differ. The order is locked; the variation is isolated.
- When to use. Several variants share the same fixed sequence and differ in a few steps, and that order must not change. Shared structure plus small, known variation.
- Structure. One abstract base with a final template method that calls abstract steps (must override), concrete steps (default), and hooks (may override). Children supply the slots.
- Inverted control. The parent calls down into the child; the child never calls up to orchestrate. "Don't call us, we'll call you." That inversion is what every test runner and servlet container sells.
- The classic gotcha. People confuse it with Strategy. Template Method varies steps inside one fixed algorithm via inheritance; Strategy swaps the whole algorithm via composition at runtime.
This is an LLD design pattern. The goal here is simple: give you enough to draw it, code it, and defend it in a top-company loop without hand-waving.
1The problem it solves#
Start with a case where copy-paste quietly rots. A report exporter is the classic one.
- You support CSV, JSON, and PDF.
- Every export does the same dance: open a connection, pull the rows, format them, write the file, close the connection.
- Four of those five steps are identical across all three formats.
- Only "format the rows" actually changes.
The naive move is three classes, each with the full five-step method copied in.
- It works on day one.
- Then someone adds a "log the export" step, and now you edit three files and forget the third.
- Three weeks later the PDF exporter is missing the log line, your metrics dashboard shows two formats reporting and one silent, and nobody knows why.
The real problem: the order and the shared steps are one decision that belongs in one place.
- Copy the skeleton into every class and you have scattered that decision across N files.
- Every change risks drift.
- Drift across three copies is exactly the bug that survives code review, because each file looks fine on its own.
Template Method's answer:
- Write the skeleton once, in a parent.
- Let each child override only the parts that genuinely differ.
- The order is locked. The variation is isolated.
- This is the Open Closed Principle in practice: the algorithm is closed for modification, open for extension through new subclasses.
Not "can you recite the UML." They want to see you name the shared structure out loud and point at the one step that varies. Spotting "same order, one slot differs" before you draw anything is the signal that you design for change, not just for today.
2The idea (mental model)#
Think of a recipe card that says:
- Prep the ingredients
- Cook
- Plate
- Clean up
The card is fixed, the "how" of each step is not.
- "Cook" means something different for pasta than for steak.
- The steps and their order are the template.
- The specific "how" of each step is left to whoever is cooking.
In code, the parent owns one method that calls the steps in order. Often named run() or execute().
- That method is the template method.
- It is usually
finalso nobody can change the order.
The steps it calls come in three flavors:
- Abstract. The child must implement them. These are the parts that always differ.
- Concrete. The parent provides a default. The child can leave it alone.
- Hooks. Empty or near-empty methods the child may override to tweak behavior, but usually does not need to.
The key inversion: the parent calls down into the child.
- The child never calls up to orchestrate.
- This is the Hollywood Principle: "don't call us, we'll call you."
- The framework holds the control flow, and that inverted control is exactly what every test runner and servlet container sells you.
3Structure#
One abstract base class holds the template method and declares the step methods. Concrete subclasses implement the steps that vary. Here is the shape for the exporter example.
export() is the public, final template method. formatRows() is abstract, so every child supplies its own. fetchRows() and writeOutput() are shared, written once in the parent. shouldCompress() is a hook with a sensible default, and only PdfExporter bothers to override it.What a reader learns at a glance:
- The base owns the algorithm, the children own one or two slots.
- Each child is about 5 lines instead of 25.
- That readability is a feature, and it is the thing the interviewer scans your whiteboard for.
final, and which should be abstract, and why does it matter?Reveal the answer
export(), the template method, should be final: it owns the step order, and a subclass that could override it could reorder or drop steps and defeat the pattern. formatRows() should be abstract: it is the part that always differs, so the base refuses to guess and forces each child to supply it. Lock the orchestration, force the variation, default the rest.4Implementation in Java#
import java.util.List;
abstract class ReportExporter {
// The template method. final so nobody reorders the steps.
public final void export() {
List<String[]> rows = fetchRows();
String body = formatRows(rows);
if (shouldCompress()) {
body = compress(body);
}
writeOutput(body);
log("Exported " + rows.size() + " rows");
}
// Shared step, same for everyone.
protected List<String[]> fetchRows() {
// pretend this hits the database
return List.of(
new String[]{"1", "Ada"},
new String[]{"2", "Linus"}
);
}
// Shared step.
protected void writeOutput(String body) {
System.out.println("Writing:\n" + body);
}
// The part that always differs. Children must implement.
protected abstract String formatRows(List<String[]> rows);
// Hook: default behavior, override only if you care.
protected boolean shouldCompress() {
return false;
}
private String compress(String body) {
return "[gzip]" + body;
}
private void log(String message) {
System.out.println("LOG: " + message);
}
}
class CsvExporter extends ReportExporter {
@Override
protected String formatRows(List<String[]> rows) {
StringBuilder sb = new StringBuilder();
for (String[] r : rows) {
sb.append(String.join(",", r)).append("\n");
}
return sb.toString();
}
}
class JsonExporter extends ReportExporter {
@Override
protected String formatRows(List<String[]> rows) {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < rows.size(); i++) {
String[] r = rows.get(i);
sb.append("{\"id\":\"").append(r[0])
.append("\",\"name\":\"").append(r[1]).append("\"}");
if (i < rows.size() - 1) sb.append(",");
}
return sb.append("]").toString();
}
}
class PdfExporter extends ReportExporter {
@Override
protected String formatRows(List<String[]> rows) {
return "%PDF rows=" + rows.size();
}
@Override
protected boolean shouldCompress() {
return true; // PDFs get compressed
}
}
The caller does not know or care which exporter it holds:
ReportExporter exporter = new JsonExporter();
exporter.export();
Read the payoff in the code:
- Every exporter runs the same five steps in the same order.
- The CSV and JSON ones never think about compression.
- The PDF one flips one hook.
- Nobody copied the skeleton.
- A new "log the export" step lands in one place,
export(), and all three formats pick it up at once. That is the drift bug from section 1, designed out.
5A real-world example#
You have already used this pattern even if you never named it.
- JUnit. The test runner calls
setUp(), then your@Testmethod, thentearDown(), in that fixed order. You fill in the slots, you do not control the order. That is Template Method with hooks, and@Before/@Afterare the hook points. - Servlets.
HttpServlethas aservice()method that inspects the request type and dispatches todoGet(),doPost(), and so on. You overridedoGet(). The container runs the surrounding flow. You never callservice()yourself. - Spring's "AbstractXyz" family. Any base named
Abstract*Templateor that hands you adoInTransactionstyle callback leans on this idea.JdbcTemplateandRestTemplateare named for it: the lifecycle (open connection, run your query, close, translate exceptions) is fixed, your logic plugs into one slot. - Sorting with
Comparable. A cousin: the sort algorithm is fixed, you supplycompareTo(), the one varying step.
In LLD rounds it hides inside bigger designs:
- A payment processor that always validates, charges, then notifies, where "charge" differs per gateway (Stripe vs Razorpay vs PayPal).
- A game turn that always draws, moves, then scores, where "move" differs per piece.
- A data pipeline with fixed extract/transform/load order and a pluggable transform.
6When to use it, and when not to#
Reach for it when:
- You have two or more methods that are nearly identical, differing in a few steps.
- The order of steps must not change across variants. The order is the thing you want to protect.
- The variation is known and small: a handful of steps, not an open-ended set.
Skip it when:
- There is really only one varying step and no fixed skeleton around it. Then you want Strategy: pass in the one behavior as an object, no inheritance needed.
- The variants need to change at runtime. Template Method bakes the choice into the subclass you instantiate. To swap behavior on a live object, Strategy wins because it is composition, not a compile-time
extends. - You would need deep inheritance trees to express it. Three levels of abstract classes to reuse code is a smell. Composition usually reads better and dodges the fragile base class problem, where a parent edit silently breaks grandchildren.
My whiteboard rule of thumb:
- Interviewer says "same steps, same order, one or two parts differ": say Template Method.
- Interviewer says "swap this behavior at runtime" or "the user picks the algorithm": say Strategy.
- They are close relatives and interviewers love poking at the line. The honest one-liner: Template Method varies steps inside one fixed algorithm via inheritance; Strategy swaps the whole algorithm via composition.
"Template Method varies steps inside one fixed algorithm via inheritance; Strategy swaps the whole algorithm via composition." Deliver that unprompted and you have answered the follow-up they were loading. It shows you chose the pattern on purpose, not by reflex.
7Common mistakes#
Leaving the template method overridable.
- If
export()is notfinal, a subclass can override it and reorder everything, which defeats the whole point. - Lock it with
final.
Making every step abstract.
- Then subclasses must implement all of them and you have gained nothing over three separate unrelated classes.
- The payoff comes from the shared concrete steps. If nothing is shared, you picked the wrong pattern.
Too many hooks.
- Five optional override points and the flow becomes impossible to reason about.
- Each subclass does something subtly different and you cannot tell what
export()does without reading every child. - Keep hooks few and well named: one or two is plenty.
Steps that leak into each other through shared mutable state.
- If
formatRows()secretly sets a field thatwriteOutput()reads, the steps are no longer independent. - A subclass that overrides one then breaks the other.
- Pass data through parameters and return values, as above with
rowsandbody.
Confusing it with Strategy and mixing them.
- Template Method uses inheritance and a fixed skeleton. Strategy uses composition and a swappable object.
- Pick one per axis of variation.
- It is fine to use both in one design, but be clear about which does what.
Protected vs private confusion.
- The varying steps must be
protected(or at least package-visible) so subclasses can override them. - The pure helpers that never vary should be
private, likecompress()andlog()above. - Candidates who make
compress()protected for no reason invite accidental overrides and widen the contract they now have to defend.
Reaching for Template Method when the interviewer actually described runtime selection. If the user picks the format from a dropdown at runtime, inheritance bakes the choice in too early and you will fight it. That is Strategy. Picking inheritance when the variation is runtime-swappable is the single most common way candidates misread this pattern.
8Where it shows up in interviews#
A few ways this lands in a real LLD round.
- Direct ask. "Design an export feature for CSV, JSON, and PDF." The instant you notice the shared steps, name Template Method, draw the base class, mark
export()as the final template method, and point at the one abstract step. That signals structure, not just classes. - The Strategy follow-up. "What if the user picks the format at runtime from a dropdown?" Lean toward Strategy, or a factory that picks the right subclass. Saying why you would switch (runtime selection favors composition over a baked-in subclass) is the answer they want.
- The hook question. "What if only PDF needs compression?" That is a hook with a default. Show
shouldCompress()returning false in the base and true in one child. It proves you understand "must implement" versus "may override." - The anti-pattern probe. "Why not just copy the method into each class?" Answer with drift: one new step means editing N files and missing one. The template centralizes the order so a change happens once. Tie it back to Open Closed and Don't Repeat Yourself.
Keep your example small.
- Three subclasses, one abstract step, one hook.
- That is enough to show mastery and leaves room to talk through tradeoffs instead of typing boilerplate for 20 minutes.
"How is this different from Strategy? When would you switch?"
"What if only one variant needs an extra step, like PDF compression?"
"Why make the template method final? What breaks if it is not?"
"Is deep inheritance a risk here? What about the fragile base class problem?"
"Can two variants share state between steps? Any danger there?"
What you can now explain in the room
- The intent in one line: fix the step order in a parent, let subclasses fill the slots that differ.
- When to reach for it (shared fixed order, small known variation) and when to skip it (runtime swap, single step, deep trees).
- The three step types (abstract must-override, concrete default, optional hook) and why the template method is final.
- Why the control flow is inverted ("don't call us, we'll call you") and where JUnit, Servlets, and JdbcTemplate use it.
- The classic gotcha: Template Method versus Strategy, inheritance inside one algorithm versus composition swapping the whole one.
- The common misuses: too many hooks, everything abstract, leaky shared state, and protected-versus-private sloppiness.
If this clicked, look at the Strategy pattern next (its runtime-swappable sibling), then Factory Method (which is itself a specialized Template Method for object creation).
Get a prep plan built around your Template Method Pattern interview
Tell us the role and your interview date. We will send back a dated, day by day plan. Free.