Template Method is a widely used design pattern and it provides great
flexibility in our designs. This is one of my favorite patterns.
Challenge
You are creating machines for creating Pizza and Burger. When we look closely we
can see all the machines have some operations in common and in the same order.
The Start operation consists of turning on the
machines, do the system check for any troubles and turning on the indicators.
The Produce operation does the respective production of item.
The Stop operation shutdowns the internal workings of the machine, turns off the
indicators and power offs the machine.
The challenge is to create more machines like Cheese Burger, Pan Pizza with less
custom implementations. We need to take care that the duplicate codes are
avoided in our design.
Definition
"Define the skeleton of an algorithm in an operation, deferring some steps to
subclasses. Template Method lets subclasses redefine certain steps of an
algorithm without changing the algorithm's structure."
Implementation
We can see that all the operation appears in the same sequence. Often the Start
and Stop operation are common to both Pizza and Burger machines.
So we can define a skeleton of algorithm (or the order of invocation) like
below:
We can see all the machines have this order of
execution. Only the Produce operation will be different.
So creating an Execute() method to incorporate this would look like:
public
class
Machine
{
public
void
Execute()
{
Start();
Produce();
Stop();
}
}
By calling the Execute() method we can invoke all the 3 methods in the right
order. Keeping the Execute() method in the base class as public, we can create
Produce() method as virtual so that it can be overridden. For more customization
we are making all the 3 methods as virtual.
Note
For virtual methods, a default implementation will be provided in the base
class. The derived class may/may not override it.
For abstract methods, we need to override them in the derived class. There won't
be any default implementation in the base class.
The modified Machine class will look like below:
public
class
Machine
{
public
void
Execute()
{
Start();
Produce();
Stop();
}
protected
virtual
void
Start()
{
Trace.WriteLine("Machine.Starting..");
}
protected
virtual
void
Produce()
{
Trace.WriteLine("Machine.Producing..");
}
protected
virtual
void
Stop()
{
Trace.WriteLine("Machine.Stopping..");
}
}
Please note the class uses virtual keyword so that the derived classes can
override.
The derived class PizzaMachine will look like:
public
class
PizzaMachine
:
Machine
{
protected
override
void
Produce()
{
Trace.WriteLine("PizzaMachine.Producing..");
}
}
The derived class BurgerMachine will look like:
public
class
BurgerMachine
:
Machine
{
protected
override
void
Produce()
{
Trace.WriteLine("BurgerMachine.Producing..");
}
}
Please note that both of them derives from Machine class and use the keyword
override to custom implement the Produce() method.
Execution
Now we can execute the PizzaMachine using the Execute() method of base class.
new
PizzaMachine().Execute();
Let us examine how the order of execution works.
-
Machine.Execute() is invoked
-
Machine.Start() is invoked
-
PizzaMachine.Produce() is invoked
-
Machine.Stop() is invoked
Please note the step 3 above, in which the execution shifts from Machine class
to PizzaMachine class. This is the power of Template Method pattern. Here the
order of execution is maintained and a custom production is done.
Note
The underlying detail of how the above code works goes to Virtual Method Table (VMT)
where the base class method address is kept in a table. The derived classes will
be having a new address for the derived method. This will be replacing the
original base class method address.
The control flow is depicted in the image below.
Test Application
A test application is created with a GUI using WinForms.
Summary
In this article we have seen the advantage of Template Method design pattern and
the problem it tries to address. The source code contains the classes and
application explained.