The Template Method Design Pattern is a behavioral design pattern that defines the skeleton of an algorithm in a base class, but allows subclasses to override specific steps of the algorithm without changing its overall structure.
It’s particularly useful in situations where:
When you're solving a problem that follows a common high-level structure but has slight variations in a few steps, it's tempting to write a single method with branching logic like if-else
or switch
statements to handle those differences.
For example, a DataExporter
might use if
conditions to export in CSV, JSON, or XML format.
But as new variations are added, the method becomes bloated, hard to follow, and violates the Single Responsibility Principle and the Open/Closed Principle.
The Template Method Pattern solves this by capturing the common workflow in a base class and pushing the customizable steps into subclasses, ensuring that the overall structure remains consistent while allowing flexibility where needed.
Let’s walk through a real-world example and see how we can apply the Template Method Pattern to build flexible, extensible, and reusable workflows.
Let’s say you’re building a tool that allows your application to export reports in different formats — such as CSV, PDF, and Excel.
On the surface, each report exporter has a different output format, but underneath, the overall process is almost identical.
Here’s the high-level workflow followed by each exporter:
Despite these similarities, if you implement each exporter naively, you'll likely duplicate a lot of logic, and that comes at a cost.
While this approach might seem straightforward at first, it comes with several serious design drawbacks:
The same steps — preparing data, opening/closing files, writing footers — are repeated in every exporter class. Add an ExcelReportExporterNaive
, and you're copying the same boilerplate for the third time.
If you decide to change how data is prepared or how files are closed (e.g., to add logging or error handling), you’ll have to update every exporter class manually — increasing the risk of introducing bugs.
Since each exporter implements the entire workflow on its own, there’s a real danger that a developer might:
This leads to inconsistent logic and fragile code.
Adding a new report format means copying a full class, pasting boilerplate, and modifying only a few lines — violating the DRY (Don't Repeat Yourself) principle.
We need a way to:
This is exactly what the Template Method Pattern is designed for.
The Template Method pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. It allows you to keep the overall structure of the process consistent, while giving subclasses the flexibility to customize specific parts of the algorithm.
final
method (e.g., exportReport()
) that defines the fixed sequence of steps for the algorithm.CsvReportExporter
, PdfReportExporter
)Think of a general recipe for baking a cake (the Template Method):
The overall baking process is fixed by the general recipe. Specific types of cakes (subclasses) only need to provide their unique batter preparation and might choose to override the frosting step.
Let’s refactor our report exporting system using the Template Method Pattern.
The goal is to extract the common report generation workflow into a single base class, while allowing each format-specific exporter to customize only the parts that differ.
AbstractReportExporter
)This class contains the template method, which defines the fixed structure of the report export process. It also defines abstract methods (to be implemented by subclasses) and hook methods (which subclasses can override if needed).
Each concrete class will extend AbstractReportExporter
and implement the format-specific steps.
Now the client code doesn’t need to worry about the internal steps of report generation. It simply creates the appropriate exporter and calls the exportReport()
method.
Using Template Method pattern, we have: