Learn about the Template Method Pattern – a Behavioral Design Pattern that allows you to define an algorithm skeleton in a parent class while letting subclasses customize specific steps without changing the overall structure.
No table of contents available for this article
Classification: Behavioral Pattern
Purpose: The Template Method Pattern allows you to build a "skeleton" of an algorithm within a method, while letting subclasses redefine specific steps without altering the overall structure of that algorithm.
Usage Frequency: Medium
Think of the Template Method like a cooking recipe: you have fixed steps (prepare ingredients → prep work → cook → plate), but each chef can execute each step in their own way. The process structure remains constant, but the implementation details are flexible.
Imagine you're developing a data mining application to analyze corporate documents. Users can provide documents in various formats such as PDF, DOC, and CSV, and the application needs to extract data from these formats and convert them into a unified format for processing.
Initially, the application only supported reading DOC files. Later, you expanded it to read CSV and PDF files as well. The result was three separate processing classes: DOCDataMiner, CSVDataMiner, and PDFDataMiner.
Looking back at the code, you notice a major issue: these three classes contain a lot of duplicate code. In reality, only the code handling each specific file format differs—the logic for opening files, analyzing data, and closing files is nearly identical.
Another problem lies in the client code. To use these classes, you have to write numerous if-else or switch-case statements to select the correct processor based on file format. The code becomes bloated and hard to maintain.
csharp
// Bloated code with multiple conditions
if (fileType == "PDF")
{
var pdfMiner = new PDFDataMiner();
pdfMiner.Process();
}
else if (fileType == "DOC")
{
var docMiner = new DOCDataMiner();
docMiner.Process();
}
else if (fileType == "CSV")
{
var csvMiner = new CSVDataMiner();
csvMiner.Process();
}The Template Method Pattern proposes a more elegant approach: break the algorithm into a series of steps, convert these steps into methods, and place all method calls within a single template method.
Specifically, you create a base class (abstract class) containing:
Template method: A method that defines the sequence of algorithm steps
Abstract methods: Steps that subclasses must implement
Hook methods (optional): Steps with default implementations that subclasses can override if needed
Subclasses inherit from the base class and only need to override the necessary methods. This eliminates duplicate code and leverages polymorphism to simplify client code.
The Template Method Pattern consists of these main components:
AbstractClass
Declares methods that serve as algorithm steps
Contains the template method—a method that calls steps in a fixed order
Steps can be abstract (requiring subclass implementation) or have default implementations
ConcreteClass
Inherits from AbstractClass
Implements abstract methods
Can override methods with default implementations
Cannot override the template method (to ensure the algorithm structure remains unchanged)
Effective code reuse: Common logic is placed in the parent class, avoiding copy-paste between subclasses
DRY Principle compliance (Don't Repeat Yourself): Completely eliminates duplicate code
High flexibility: Allows subclasses to customize specific steps without affecting the overall structure
Easy to extend: When supporting new file formats, simply create a new subclass and implement the abstract methods
Difficult to maintain with many steps: If the template method has too many steps (abstract methods), maintenance and tracking become complex
Inheritance constraints: This pattern relies on inheritance, which can cause issues with languages that only support single inheritance
Potential LSP violation: In some cases, if a subclass suppresses a default step, it may violate the Liskov Substitution Principle
Consider using Template Method when:
You have a multi-step algorithm and want to allow subclasses to customize certain steps while keeping the overall structure intact
You notice multiple classes with similar code that differs only in a few implementation details
You want to control extension points of the algorithm—allowing subclasses to extend at specific points rather than everywhere
You want to apply the "Hollywood Principle": "Don't call us, we'll call you"—the parent class calls the subclass, not the other way around
Problem: Build a data mining application for PDF, DOC, and CSV files.
csharp
abstract class DataMiner
{
// Properties
public string File { get; set; }
public string RawData { get; set; }
// Hook methods - have default implementation
public virtual void OpenFile(string path)
{
Console.WriteLine($"Opening file: {path}");
}
public virtual void CloseFile()
{
Console.WriteLine("Closing file...\n");
}
// Abstract methods - subclasses must implement
public abstract void ExtractData();
public abstract void ParseData();
// Template Method - defines the algorithm skeleton
public void Mine(string path)
{
OpenFile(path);
ExtractData();
ParseData();
CloseFile();
}
}csharp
class CSVDataMiner : DataMiner
{
public override void ExtractData()
{
Console.WriteLine("Extracting data from CSV file...");
RawData = "CSV raw data";
}
public override void ParseData()
{
Console.WriteLine("Parsing CSV data into structured format...");
}
}
class PDFDataMiner : DataMiner
{
public override void OpenFile(string path)
{
base.OpenFile(path);
File = "PDF";
Console.WriteLine("PDF reader initialized.");
}
public override void ExtractData()
{
Console.WriteLine($"Extracting data from {File} file...");
RawData = "PDF raw data";
}
public override void ParseData()
{
Console.WriteLine($"Parsing {RawData} into structured format...");
}
}csharp
class Program
{
static void Main(string[] args)
{
Console.WriteLine("=== PDF Data Mining ===");
DataMiner pdfMiner = new PDFDataMiner();
pdfMiner.Mine("documents/report.pdf");
Console.WriteLine("=== CSV Data Mining ===");
DataMiner csvMiner = new CSVDataMiner();
csvMiner.Mine("data/sales.csv");
}
}Output:
=== PDF Data Mining ===
Opening file: documents/report.pdf
PDF reader initialized.
Extracting data from PDF file...
Parsing PDF raw data into structured format...
Closing file...
=== CSV Data Mining ===
Opening file: data/sales.csv
Extracting data from CSV file...
Parsing CSV data into structured format...
Closing file...Factory Method Pattern
Factory Method can be viewed as a specialized form of Template Method
Factory Method often serves as a step within Template Method
Strategy Pattern
Template Method is based on inheritance: changing part of an algorithm by extending in subclasses
Strategy is based on composition: changing behavior by providing different strategy objects
Template Method operates at the class level and is static (determined at compile time)
Strategy operates at the object level, allowing behavior changes at runtime
If you found this article helpful, explore more in the Design Patterns Series to enhance your programming skills!
[1] Refactoring.Guru. https://refactoring.guru/design-patterns
[2] Design Patterns for Dummies, Steve Holzner, PhD
[3] Head First Design Patterns, Eric Freeman
[4] Gang of Four Design Patterns 4.0
[5] Dive into Design Patterns