In one sentence: Template Method defines the skeleton of an algorithm in one operation and defers some steps to subclasses, letting them redefine those steps without changing the algorithm's structure.
Real-world analogy
Every branch of a franchise opens the morning the same way, because head office wrote the routine down: unlock, clean the floor, stock the shelves, count the till float, flip the sign. Five steps, that order, everywhere.
One of those steps is deliberately left blank. "Stock the shelves" means croissants out of the proving oven at a bakery and new releases onto the front table at a bookstore — head office has no idea what your branch sells and doesn't want to. Other steps come with a default you may quietly override: the manual says play the standard playlist, and if your branch prefers local radio, fine. The blanks you must fill and the ones you may are marked differently in the manual, so a new franchisee knows which is which.
What no branch may do is reorder. Opening the doors before counting the float isn't initiative, it's a failed audit. And notice the direction of control: head office's routine calls into your branch's steps at the moments it chooses. Your branch never runs the routine its own way and calls head office when convenient.
Mapping the analogy to the pattern:
- The manual's fixed opening sequence → the template method, non-virtual precisely so no branch can rewrite the order.
- "Stock the shelves," left blank → a pure virtual primitive operation: every ConcreteClass must supply its own.
- "Play the standard playlist unless you prefer otherwise" → a hook: a default body a subclass may override and may ignore.
- The bakery and the bookstore → ConcreteClasses, supplying steps and nothing else — no branch owns any control flow.
- Head office calling the branch, never the reverse → the Hollywood principle: AbstractClass runs the algorithm and rings down for the steps.
Another angle: a pre-flight checklist. The sequence is fixed by regulation and identical across the fleet; the aircraft-specific items inside it are filled in per type, and no crew gets to reorder the list because they're in a hurry.
The problem
GoF's example is an application framework whose Application class knows how to open a document — check it can be opened, create it, register it, read it — while every application built on the framework supplies its own document type and its own way of reading it. Ours is smaller: you need to export the same table as CSV and as HTML. Both exports open something, write each row, and finish up — in exactly that order.
- Copy-paste drift. Writing each exporter end to end duplicates the loop, and the two copies slowly diverge.
- The order is not enforced. Nothing stops a new exporter from writing rows before the header, and the bug only shows up in the output file.
- Shared fixes must be applied twice. Change how rows are counted and you change it in every exporter you ever wrote.
The solution
Write the sequence once, in the base class:
- Put the algorithm in a non-virtual method — the template method. It calls the steps in order.
- Declare the steps that vary as virtual (pure virtual when a subclass must supply them).
- Optionally add hooks: virtual steps with a harmless default body that subclasses may ignore.
Subclasses fill in the steps. Because the skeleton is not virtual, no subclass can reorder or skip a step.
The distinction in steps 2 and 3 is the one GoF insists you make explicit. Abstract operations must be overridden; hook operations may be, and usually do nothing by default. Somebody writing a subclass has to know which is which to reuse your base class at all, so say it in the code: pure virtual for the first kind, an empty virtual body for the second.
Note: GoF's C++ advice is exactly what the example does, and it is worth copying. Declare the primitive operations
protected, so nothing but the template method can call them; make the ones that must be supplied pure virtual; and make the template method itself non-virtual, since it is the one thing subclasses must not redefine. GoF adds a fourth piece of advice: keep the number of primitive operations small, because every one of them is another blank a subclass author has to fill in.
Note: The name predates C++ and has nothing to do with C++ templates. It's called a template because the base method is a fill-in-the-blanks form, not because it involves
template<typename T>. (You can build a compile-time version with CRTP, but that's an implementation choice, not the pattern.)
Structure
This is the smallest structure in the catalogue — only two participants:
- AbstractClass — implements the template method that defines the algorithm's skeleton, and declares the abstract primitive operations that concrete subclasses fill in. The template method calls those primitives alongside its own concrete operations and operations on other objects.
ReportGeneratorhere; GoF's isApplication. - ConcreteClass — implements the primitive operations to carry out its own version of the steps, and relies on AbstractClass for the invariant parts.
CsvReportandHtmlReport.
C++ example
Two report generators sharing one header → rows → footer skeleton. writeFooter is a hook with a do-nothing default, so CSV simply skips it.
#include <iostream>
#include <memory>
#include <string>
#include <vector>
struct Row {
std::string city;
int visitors;
};
class ReportGenerator {
public:
virtual ~ReportGenerator() = default;
// The template method: fixed order, deliberately NOT virtual.
void generate(const std::vector<Row>& rows) const {
writeHeader();
for (const Row& r : rows) writeRow(r);
writeFooter();
}
protected:
virtual void writeHeader() const = 0;
virtual void writeRow(const Row& r) const = 0;
virtual void writeFooter() const {} // hook: optional to override
};
class CsvReport : public ReportGenerator {
protected:
void writeHeader() const override { std::cout << "city,visitors\n"; }
void writeRow(const Row& r) const override {
std::cout << r.city << "," << r.visitors << "\n";
}
};
class HtmlReport : public ReportGenerator {
protected:
void writeHeader() const override { std::cout << "<table>\n"; }
void writeRow(const Row& r) const override {
std::cout << " <tr><td>" << r.city << "</td><td>" << r.visitors << "</td></tr>\n";
}
void writeFooter() const override { std::cout << "</table>\n"; }
};
int main() {
const std::vector<Row> rows{{"Nairobi", 1200}, {"Lisbon", 830}};
std::vector<std::unique_ptr<ReportGenerator>> reports;
reports.push_back(std::make_unique<CsvReport>());
reports.push_back(std::make_unique<HtmlReport>());
for (const auto& report : reports) {
report->generate(rows);
std::cout << "---\n";
}
}city,visitors
Nairobi,1200
Lisbon,830
---
<table>
<tr><td>Nairobi</td><td>1200</td></tr>
<tr><td>Lisbon</td><td>830</td></tr>
</table>
---Both reports ran the identical loop in generate(); only the three small steps differed, and neither subclass could have got the order wrong.
When should you use it?
GoF gives three reasons. Use Template Method:
- To implement the invariant parts of an algorithm once, leaving the parts that vary to subclasses.
- To factor common behavior out of several subclasses and localize it in one place, removing the duplication. GoF calls this "refactoring to generalize": find what differs between existing classes, pull those differences into new operations, and replace the differing code with a template method that calls them.
- To control how subclasses extend you. A template method that calls hook operations at chosen points permits extension only at those points — and nowhere else.
Pros and cons
Pros (GoF's consequences)
- A fundamental technique for code reuse, and GoF notes it matters most in class libraries, where it is the mechanism for factoring shared behavior into the library's base classes.
- Control is inverted — GoF's name for this is the Hollywood principle: "Don't call us, we'll call you." The parent class calls the subclass's operations, never the reverse, which is why the base class can guarantee the order.
- Extension points are explicit. Because you label operations as abstract (must override) or hooks (may override), it is clear what a subclass is allowed to change.
- Fixes to the shared sequence land in every subclass at no cost, and subclasses stay tiny — they supply steps, not control flow.
Cons
- Locks you into inheritance, and a subclass gets the whole base class whether it wants it or not.
- The skeleton can become rigid; a variant needing a different order doesn't fit.
- Reading a subclass alone doesn't tell you when its steps run — you must read the base too.
- Every additional primitive operation is another thing a subclass author must implement, so the pattern degrades if the base class asks for too many.
How to remember it
Memory hook: "Don't call us, we'll call you." The base class runs the show and rings the subclass when it needs a step done — which is why the sequence is safe no matter who subclasses you. Against its confusable sibling Strategy: inheritance fills in the blanks of a fixed recipe, composition swaps the whole recipe.
Related patterns
- Factory Method — GoF notes that factory methods are frequently called by template methods; in the book's example, the template method
OpenDocumentcalls the factory methodDoCreateDocumentto get the right kind of document. - Strategy — GoF's own one-line contrast: template methods use inheritance to vary part of an algorithm, strategies use delegation to vary the entire algorithm.
- Observer — GoF recommends sending notifications from a template method in the subject, with
Notify()as the final step, so observers never see a half-updated subject.