Summary: in this tutorial, you’ll learn about the Template Method pattern and how to implement it in C#.
Introduction to the C# Template Method Pattern
The Template Method pattern defines a skeleton of an algorithm in a superclass and allows subclasses to redefine specific steps of the algorithm without changing its structure.
The following UML diagram illustrates the Template Method pattern:
Typically, the Template Method consists of an abstract class that defines the structure of the algorithm and concrete subclasses that implement the specific steps of the algorithm.
The abstract class provides a set of template methods that the subclasses can override to provide their own implementation.
In practice, you use the Template Method pattern when you have an algorithm that you need to implement in a similar way across multiple classes but with some slight variations.
Instead of duplicating the same code across different classes, you can define a standard template in a superclass, and then override some methods in the subclasses to customize the corresponding algorithm steps.
The Template Method pattern reduces code duplication, increases code reuse, and makes it easier to maintain and modify the algorithm in the future.
C# Template Method pattern example
The following program demonstrates how to use the Template Method pattern to define a generic algorithm for reading data from a file, transforming it, and storing it in a database while allowing subclasses to override specific steps to handle different file formats and database types:
namespace TemplateMethodPattern;
// Abstract class that defines the template method
// and its steps
public abstract class ETL
{
public void ImportData(string filename)
{
// Step 1: read data from file
var data = Extract(filename);
// Step 2: transform data
var transformedData = Transform(data);
// Step 3: store data in database
Load(transformedData);
}
protected abstract string[] Extract(string filename);
protected virtual string[] Transform(string[] data)
{
// Default implementation of transformation
// that does nothing
return data;
}
protected abstract void Load(string[] data);
}
// Concrete subclass that handles
// CSV files and SQL Server database
public class CSVToSQLServer : ETL
{
protected override string[] Extract(string filename)
{
// Read CSV file and return data as an array of strings
return File.ReadAllLines(filename);
}
protected override void Load(string[] data)
{
// Store data in SQL Server database
// Implementation omitted for brevity
Console.WriteLine("Store Data in SQL Server");
}
}
// Concrete subclass that handles
// Excel files and MySQL database
public class ExcelToMySQL : ETL
{
protected override string[] Extract(string filename)
{
// Read Excel file and return data as an array of strings
// Implementation omitted for brevity
return new string[] { "1,2,3", "4,5,6" };
}
protected override string[] Transform(string[] data)
{
// Transform Excel data to CSV format
// Implementation omitted for brevity
Console.WriteLine("Excel data transformed to CSV format");
return data;
}
protected override void Load(string[] data)
{
// Store data in MySQL database
// Implementation omitted for brevity
Console.WriteLine("Data stored in MySQL");
}
}
public class Program
{
static void Main(string[] args)
{
// Import CSV data into SQL Server
var csvSqlServerImport = new CSVToSQLServer();
csvSqlServerImport.ImportData("data.csv");
// Import Excel data into MySQL
var excelMySqlImport = new ExcelToMySQL();
excelMySqlImport.ImportData("data.xlsx");
}
}
Code language: C# (cs)
How it works.
First, define an abstract class called ETL
(Extract, Transform, Load) that contains the template method called ImportData
.
The ImportData
method defines the steps to import data from a file, transform the data, and load it into a database.
The ImportData
method calls three abstract methods, Extract
, Transform
, and Load
, which represent the specific steps of the ETL process:
- The
Extract
method is responsible for reading data from a file. - The
Transform
method transforms the data. - The
Load
method saves the transformed data in a database.
We mark the Extract
and Load
methods as abstract
so that the subclasses need to implement them. We also mark the Transform
method as virtual
and provide a default implementation. The subclasses can override the Transform
method if necessary:
// Abstract class that defines the template method
// and its steps
public abstract class ETL
{
public void ImportData(string filename)
{
// Step 1: read data from file
var data = Extract(filename);
// Step 2: transform data
var transformedData = Transform(data);
// Step 3: store data in database
Load(transformedData);
}
protected abstract string[] Extract(string filename);
protected virtual string[] Transform(string[] data)
{
// Default implementation of transformation
// that does nothing
return data;
}
protected abstract void Load(string[] data);
}
Code language: C# (cs)
Second, define the
class that inherits from the CSV
ToSQLServerETL
class. The
implements the CSV
ToSQLServerExtract()
method to read data from a CSV
file and the Load()
method to store the data in a SQL Server database:
// Concrete subclass that handles
// CSV files and SQL Server database
public class CSVToSQLServer : ETL
{
protected override string[] Extract(string filename)
{
// Read CSV file and return data as an array of strings
return File.ReadAllLines(filename);
}
protected override void Load(string[] data)
{
// Store data in SQL Server database
// Implementation omitted for brevity
Console.WriteLine("Store Data in SQL Server");
}
}
Code language: C# (cs)
Third, define the ExcelToMySQL
class that extends the ETL
class. The CSVToSQLServer
class implements the Extract()
method to read data from an Excel file and the Load()
method to store the data in a MySQL Server database:
// Concrete subclass that handles
// Excel files and MySQL database
public class ExcelToMySQL : ETL
{
protected override string[] Extract(string filename)
{
// Read Excel file and return data as an array of strings
// Implementation omitted for brevity
return new string[] { "1,2,3", "4,5,6" };
}
protected override string[] Transform(string[] data)
{
// Transform Excel data to CSV format
// Implementation omitted for brevity
Console.WriteLine("Excel data transformed to CSV format");
return data;
}
protected override void Load(string[] data)
{
// Store data in MySQL database
// Implementation omitted for brevity
Console.WriteLine("Data stored in MySQL");
}
}
Code language: C# (cs)
Finally, the Main()
method of the program uses the
and CSV
ToSQLServerExcelToMySQL
classes to import data from CSV and Excel files and save the data to a SQL Server and MySQL, respectively.
public class Program
{
static void Main(string[] args)
{
// Import CSV data into SQL Server
var csvSqlServerImport = new CSVToSQLServer();
csvSqlServerImport.ImportData("data.csv");
// Import Excel data into MySQL
var excelMySqlImport = new ExcelToMySQL();
excelMySqlImport.ImportData("data.xlsx");
}
}
Code language: C# (cs)
Summary
- Use the Template Method pattern to define the skeleton of an algorithm in a superclass and allow subclasses to override specific steps of the algorithm without changing its structure.