Template Method
- Defines the skeleton/template of an algorithm in an operation, deferring some steps to subclasses. This pattern lets subclasses redefine certain steps of an algorithm without changing the algorithm‘s structure.
Classical Structure
Scenario
- Build a banking app and report all user activities in audit trail. Every time user performs a task, report who did what and when within an audit trail
Problem
- Code duplication, every time you create a new task you have to follow the structure. Add private field AuditTrail and initialize in the constructor
- Developer should be forced to follow the structure which is missing
public class AuditTrail
{
public void Record()
{
Console.WriteLine("Audit");
}
}
public class GenerateReportTask
{
AuditTrail auditTrail;
public GenerateReportTask(AuditTrail auditTrail)
{
this.auditTrail = auditTrail;
}
public void Execute()
{
auditTrail.Record();
Console.WriteLine("Generate report");
}
}
public class TransferMoneyTask
{
private AuditTrail auditTrail;
public TransferMoneyTask(AuditTrail auditTrail)
{
this.auditTrail = auditTrail;
}
public void Execute()
{
auditTrail.Record();
Console.WriteLine("Transfer money");
}
}
Solution
public class AuditTrail
{
public void Record()
{
Console.WriteLine("Audit");
}
}
public abstract class Task
{
private AuditTrail auditTrail;
public Task()
{
auditTrail = new AuditTrail();
}
public void Execute()
{
auditTrail.Record();
DoExecute();
}
protected abstract void DoExecute();
}
public class GenerateReportTask : Task
{
protected override void DoExecute()
{
Console.WriteLine("Generate report");
}
}
public class TransferMoneyTask: Task
{
protected override void DoExecute()
{
Console.WriteLine("Transfer money");
}
}
public class Program
{
static void Main(string[] args)
{
var transferMoneyTask = new TransferMoneyTask();
transferMoneyTask.Execute();
var generateReportTask = new GenerateReportTask();
generateReportTask.Execute();
}
}
Example Structure
Example Code