Template Method Pattern in C#: Definition, Examples, Pros, Cons, and Use Cases
The Template Method pattern in C# is a behavioral design pattern that defines the skeleton of an algorithm in a base class while allowing subclasses to customize specific steps.
The Template Method pattern defines a fixed sequence of operations inside a base class method called the template method. Some steps of the algorithm are implemented directly in the base class, while others are declared abstract or virtual for subclasses to override. This pattern promotes code reuse by centralizing common workflow logic while still supporting customization. The algorithm structure remains unchanged, but subclasses can modify selected parts of the behavior. In C#, the Template Method pattern is commonly used in frameworks, data processing pipelines, report generation systems, and application lifecycle management.
Why We Use Template Method Pattern in C#?
We use the Template Method pattern in C# to:
• Reuse common algorithm logic
• Avoid duplicated workflow code
• Enforce a fixed processing sequence
• Allow subclasses to customize behavior
• Improve maintainability
• Support extensibility
• Follow the Hollywood Principle
• Standardize application workflows
When Should We Use Template Method Pattern in C#?
The Template Method pattern should be used when:
• Multiple classes share the same workflow structure
• Only some algorithm steps vary
• Processing order must remain fixed
• Common behavior should be centralized
• Framework-style extensibility is needed
• Subclasses should customize partial behavior
• You want controlled inheritance-based customization
Common Programming Problems Solved by Template Method Pattern
• Data import/export workflows
• Report generation systems
• Game engine loops
• Application startup pipelines
• Authentication workflows
• Build and deployment pipelines
• File processing systems
• Parsing and transformation workflows
Structure of Template Method Pattern in C#
Typical participants:
• Abstract Class
• Template Method
• Primitive Operations
• Concrete Classes
• Client
Basic workflow:
• Client calls template method
• Base class executes fixed algorithm structure
• Variable steps are delegated to subclasses
• Subclasses implement custom behavior
Template Method Pattern Examples in C#
Example 1: Data Processing System
Different file types should follow the same processing workflow but implement custom parsing logic.
using System;
public abstract class DataProcessor
{
public void Process()
{
ReadData();
ProcessData();
SaveData();
}
protected abstract void ReadData();
protected virtual void ProcessData()
{
Console.WriteLine("Processing data");
}
protected virtual void SaveData()
{
Console.WriteLine("Saving data");
}
}
public class CsvProcessor : DataProcessor
{
protected override void ReadData()
{
Console.WriteLine("Reading CSV file");
}
}
public class JsonProcessor : DataProcessor
{
protected override void ReadData()
{
Console.WriteLine("Reading JSON file");
}
}
public class Program
{
public static void Main()
{
DataProcessor csv = new CsvProcessor();
csv.Process();
Console.WriteLine();
DataProcessor json = new JsonProcessor();
json.Process();
}
}
Example 2: Beverage Preparation Workflow
Different beverages should follow the same preparation steps with custom brewing methods.
using System;
public abstract class Beverage
{
public void Prepare()
{
BoilWater();
Brew();
PourIntoCup();
AddCondiments();
}
private void BoilWater()
{
Console.WriteLine("Boiling water");
}
protected abstract void Brew();
private void PourIntoCup()
{
Console.WriteLine("Pouring into cup");
}
protected abstract void AddCondiments();
}
public class Tea : Beverage
{
protected override void Brew()
{
Console.WriteLine("Steeping tea");
}
protected override void AddCondiments()
{
Console.WriteLine("Adding lemon");
}
}
public class Coffee : Beverage
{
protected override void Brew()
{
Console.WriteLine("Brewing coffee");
}
protected override void AddCondiments()
{
Console.WriteLine("Adding sugar and milk");
}
}
public class Program
{
public static void Main()
{
Beverage tea = new Tea();
tea.Prepare();
Console.WriteLine();
Beverage coffee = new Coffee();
coffee.Prepare();
}
}
Example 3: Report Generation System
Reports should follow a common generation workflow with different formatting logic.
using System;
public abstract class ReportGenerator
{
public void GenerateReport()
{
FetchData();
FormatReport();
ExportReport();
}
protected virtual void FetchData()
{
Console.WriteLine("Fetching data");
}
protected abstract void FormatReport();
protected virtual void ExportReport()
{
Console.WriteLine("Exporting report");
}
}
public class PdfReport : ReportGenerator
{
protected override void FormatReport()
{
Console.WriteLine("Formatting PDF report");
}
}
public class ExcelReport : ReportGenerator
{
protected override void FormatReport()
{
Console.WriteLine("Formatting Excel report");
}
}
public class Program
{
public static void Main()
{
ReportGenerator pdf = new PdfReport();
pdf.GenerateReport();
Console.WriteLine();
ReportGenerator excel = new ExcelReport();
excel.GenerateReport();
}
}
Most Known Real-World Use Cases in C#
• ASP.NET page lifecycle
• Entity Framework processing pipelines
• Game engine update loops
• Report generation systems
• Data import/export frameworks
• Testing frameworks
• Build systems
• File parsing frameworks
• Authentication workflows
Advantages of Template Method Pattern in C#
• Promotes code reuse
• Reduces duplicate code
• Standardizes workflows
• Simplifies maintenance
• Supports controlled extensibility
• Encourages consistent processing order
• Improves readability
• Works well in frameworks
Disadvantages (Weak Points) of Template Method Pattern in C#
• Relies heavily on inheritance
• Can create rigid class hierarchies
• Difficult to change algorithm structure
• Subclasses may become tightly coupled
• Violates composition-over-inheritance principle
• Large base classes may become complex
• Runtime flexibility is limited
Comparison with Similar Patterns
| Pattern | Main Purpose | Customization Method | Relationship Type | Typical Usage | Main Difference from Template Method |
|---|---|---|---|---|---|
| Template Method | Define algorithm skeleton | Inheritance | Base-subclass | Framework workflows | Defines fixed workflow structure with overridable steps |
| Strategy | Switch algorithms dynamically | Composition | Object composition | Payment systems, sorting | Uses interchangeable objects instead of inheritance |
| State | Change behavior by state | State transitions | Composition | Workflows, FSMs | Behavior changes dynamically according to object state |
| Factory Method | Create objects through subclasses | Inheritance | Base-subclass | Object creation frameworks | Focuses on object creation instead of workflow structure |
| Command | Encapsulate operations | Command objects | Composition | Undo/redo systems | Encapsulates requests rather than algorithm templates |
Simplified UML-Style Structure
| Component | Responsibility |
|---|---|
| AbstractClass | Defines template method and common workflow |
| Template Method | Defines fixed algorithm structure |
| Primitive Operations | Steps implemented or overridden by subclasses |
| ConcreteClass | Provides custom step implementations |
| Client | Uses abstract class interface |