The Template Method Pattern is very easy to understand and implement. Here’s
the definition borrowed from
Design Patterns: Elements of Reusable Object-Oriented Software book:
“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.”
Let’s try to understand the pattern walking through a simple example. For implementing
the solution we’ll use Delphi XE, but it should work for previous versions as well.
This is the wording of the example:
Design an application that allows drawing different styles of houses (ei. country
house, city house) using ASCII art [1].
In the following image there’s a prototype of the user interface.
The GUI is composed by a form, a memo [2], two buttons, a label and a combo box.
Using the combo box you can choose whether your house will have a chimney or not.
Clicking the buttons will result in an ASCII house printed out in the memo area.
In the example above, the Draw Country House was clicked. If you click the other
button, you will get city house like the one below:
What happens if you select “No” in the combo box? Try it and let me know :-)
Here’s the link to the EXE. This EXE is harmless; I am not a bad guy: no Trojans,
no viruses, just Delphi :-)
Now, what classes do we need to make this work? Take a look at the following
class diagram and try to make sense of it:
We have an abstract superclass
THouse, which contains four abstract (pure virtual) methods: BuildFloor, BuildWalls, BuildRoof and BuildChimney. These methods are implemented in the descending classes TCountryHouse and TCityHouse. Pay
special attention to the method BuildIt in THouse. This method
is an instance method that is inherited by both concrete subclasses: TCountryHouse and TCityHouse.
I want to be more detailed:
The BuildIt method is implemented just once in the class THouse. The subclasses
TCountryHouse andTCityHouse don’t have to implement the BuildIt method.
The BuildFloor, BuildWalls, BuildRoof and BuildChimney methods have no implementation under the THouse class. The TCountryHouse has one implementation of these methods, while TCityHouse have a different
implementation of them.
This is how the BuildIt method looks like:
function THouse.BuildIt: string;
begin
Result:= BuildRoof +
BuildWalls +
BuildFloor;
if FHasChimney then
Result:= BuildChimney+ Result;
end;
This method defines a general algorithm to build a house…it doesn’t take into
consideration the kind of house that’s been built. Notice that the steps for building
the roof, walls, floor and chimney (if any) have been deferred to the subclasses.
The BuildIt method is known as a template method that gives the name to this pattern.
Let me give you an idea of the implementation of the BuildFloor method. This
method is implemented directly by the subclasses. Take a look:
function TCountryHouse.BuildFloor: string;
begin
Result:=
'~~~~~" "~~~~~~~~~~~~~~~~~~~~~~~~ ';
end;
function TCityHouse.BuildFloor: string;
begin
Result:=
'******************____****************'#13#10 +
'**************************************';
end;
Notice that the implementation of the BuildFloor method is different
in both subclasses TCountryHouse and TCityHouse.
For the implementation of the remaining methods refer to reference [5]. For the
full source code refer to [3].
In conclusion, the template method pattern needs an abstract superclass to implement
a template method (common for all subclasses). The steps within this template method
are deferred into methods that are implemented by the concrete subclasses. Did you
get it? :-)
Do you want to know more about design patterns? The books in reference [4] are
just what you need.
References:
[1] I am borrowing the ASCII designs from
Asciiworld.com
: House.
[2] Make sure to use a fixed-width font (Courier, Monaco, Courier New, Lucida
Console, etc.) for the memo, otherwise the drawing will look fuzzy.
[3] Get the full source code of this example
here. If you liked it, please, consider to make a small donation to help the
children of the world. You can make your tax deductible donation to UNICEF by clicking
here. Remember: "Children are the hope of the world",
José Martí.
[4] Books on Design Patterns: