Chapter3 TemplateMethod
Chapter3 TemplateMethod
Contents
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3.5 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1
3.1 Introduction
In this chapter, you will learn all about the Template Method design pattern. It uses
public inheritance as basic strategy for its implementation. Therefore, public inheritance
as an object oriented programming (OOP) concept and its implementation using C++ is
introduced. To explain the inner working of Template Method, it is contrasted with the
structure of a system that evolved through the application of the pull up method refac-
toring, which is also introduced in this chapter. After explaining the Template Method
through discussing its inner working, its consequences, some implementation issues, as
well as some common misconceptions and related patterns, we provide example imple-
mentations and conclude with exercises.
non-virtual methods
The implementation of these methods are provided in the class that defines them.
2
Figure 1: Class diagram showing inheritance
virtual methods
These are methods for which a default operation is supplied by the class that de-
fines them, but may be overridden in classes that are derived from the class that
defines them. These methods are declared virtual in the class definition. A default
implementation may be supplied, like the pay(float) implementation in the above
example. The default operation may also be empty. An empty default implemen-
tation is indicated as such by adding {} after the method declaration in the class
definition.
In UML virtual and pure virtual methods are written using an italic font.
3
c l a s s Employee {
public :
Employee ( char∗ theName , f l o a t thePayRate ) ;
protected :
char∗ name ;
f l o a t payRate ;
};
#endif
You will notice that the instance variables are protected and not private as we are used
to. This is to give the methods of any derived classes of this class access to these variables.
The methods of this class will typically be defined in a file called Employee.C. The code in
this file must be combined with the above mentioned definition when compiling the code.
This is achieved by including the statement #include "Employee.h" at the beginning
if this file. The pay(float) method is declared virtual to enable the derived class to
override it. The following is the implementation of the methods in this class. Note how the
constructor body is empty because all the instance variables are initialised in an initialiser
list. Be careful when you do this with char * parameters.
#include ” Employee . h”
using namespace s t d ;
4
needed. In these cases, it would be best if the constructor allocates separate memory so
that name and theName are not dependent on each other.
The following is the class definition of the Manager class:
#i f n d e f MANAGER H
#define MANAGER H
#include ” Employee . h”
protected :
bool s a l a r i e d ;
};
#endif
The line class Manager : public Employee causes Manager to inherit all the public
and protected data and methods of Employee. Only the data and methods of Manager
that are additional to those inherited from Employee are included in the class diagram
of Manager and need to be written in code. When writing the code to implement these
methods one should call the methods in the Employee rather than rewriting the code. It
is important to avoid duplicating code. Duplicate code is undesirable because you face
the risk that alteration to such code may lead to inconsistencies in the behaviour of the
system when not all the instances of that code is updated.
The following is an example of how the constructor of the derived class can be imple-
mented. Once again it uses an initialiser list to initiate all its instance variables. The first
item in this list is a call to the constructor of its parent class.
Manager : : Manager ( char∗ theName , f l o a t thePayRate ,
bool i s S a l a r i e d ) :
Employee ( theName , thePayRate ) , s a l a r i e d ( i s S a l a r i e d ) {}
In this example the calculation depends on whether the manager is salaried or not. If
the manager is salaried his/her flat pay rate is returned, otherwise, it makes the same
calculation as a regular Employee simply by calling the existing method.
f l o a t Manager : : pay ( f l o a t hoursWorked ) const
{
i f ( s a l a r i e d ) return payRate ;
return Employee : : pay ( hoursWorked ) ;
}
Note how the class name of the parent class is needed to call the method in the parent
class. Without this specification this statement will call the current method. Then it will
be an infinite recursive call.
5
Manager objects can be used just like Employee objects in any code that uses these classes.
However, it has additional methods that is usable only by Manager objects.
3.3.1 Identification
Name Classification Strategy
Template Method Behavioural Inheritance
Intent
Define the skeleton of an algorithm in an operation, deferring some steps to sub-
classes. Template Method lets subclasses redefine certain steps of an algorithm
without changing the algorithm’s structure. ([2]:325)
3.3.2 Structure
The structure of the Template Method design pattern is given in Figure 2. The design
pattern comprises of two classes, the abstract class which defines the interface and the
template method function. This function defers implementation of primitive operations
to its subclass.
3.3.3 Problem
Two different components have significant similarities, but demonstrate no reuse of com-
mon interface or implementation. If a change common to both components becomes
necessary, duplicate effort must be expended [3].
6
Figure 2: The structure of the Template Method pattern
Parent Class Parent Class
Derived Class 1 Derived Class 2 Derived Class n Derived Class 1 Derived Class 2 Derived Class n
3.3.4 Participants
AbstractClass
ConcreteClass
3.4.1 Clarification
The Template Method pattern prescribes the use of a template method. Usually a tem-
plate method is described as an algorithm with pluggable steps. Some of the steps of
the algorithm may be handled by the class defining the template method while others
are pluggable. The pluggable steps are declared as abstract (virtual) methods and may
therefore be overridden in subclasses.
7
The Template Method pattern does something similar to the outcome of pull up method
refactoring mentioned in Section 3.2.3, just the other way around. Instead of having
multiple methods calling a common method, the template method contains one or more
statements calling abstract methods. These abstract methods have varying implementa-
tions situated in subclasses. Figure 3 illustrates the difference between the outcome of
pull up method refactoring and the application of the Template Method pattern. After
application of the pull up method refactoring, multiple methods in multiple subclasses
call the master method that is implemented in the parent class. In the application of the
Template Method pattern, the master method in the parent class calls methods that are
implemented in subclasses. This is referred to as the Hollywood principle: Don’t call us,
we’ll call you coined by Sweet [9].
Three types of operations can be defined in the body of a template method. These coincide
with the three types of methods that are distinguished in OOP:
invariant operations
These are steps in the algorithm that are the same for all objects regardless to
which derived class they may belong. These steps are implemented using non-virtual
methods.
optional operations
These are steps that may be skipped under certain conditions. These methods
are declared virtual in the class definition and provided with an empty default
implementation. The designer of a subclass can decide whether it needs to be
implemented or not. If a subclass does not implement such step it is skipped in the
execution of the algorithm for objects of that subclass.
variant operations
These are steps that was identified as the pluggable parts of the algorithm. They
have to be implemented in the derived classes. They are defined as pure virtual
methods in the class definition.
• The system is easier to extend since a new class that has to use the algorithm
described by the template method need not implement the whole algorithm, but
only the parts that may vary.
• Coupling is reduced because classes that call the template method is separated from
the concrete classes. There are less dependencies because they depend only on the
abstract class and never communicate directly with the concrete classes.
8
3.4.3 Implementation Issues
Following the advice of [8], the virtual methods should be declared private. If a method
is private in a parent class it cannot be called by methods in its subclasses. Therefore,
these methods can only be invoked through calling the template method itself – which is
exactly what is intended.
A problem with the Template Method pattern that was pointed out by [5] is that by its
nature, it promotes false is-a relations. You are advised to be cautious about this and
diligent in maintaining semantic integrity in your code.
Another problem that often arises when applying the Template Method Pattern is added
complexity caused by the fragmentation of the code implementing the algorithm. The
algorithm is implemented in a number of methods of which some are implemented in
the base class and others are implemented in the derived classes. In order to minimise
such fragmentation, you are advised to minimise the number of virtual and pure virtual
methods defined for template methods. More virtual methods increases the flexibility but
also increases the complexity and maintainability of the system.
9
Strategy uses delegation to defer the implementation of a complete algorithm while
the Template Method pattern uses inheritance to defer only specific parts of an
algorithm.
Factory Method
Although the Factory Method is not a specialisation of the Template Method pat-
tern, it is related to the Template Method pattern. Many of the non-virtual methods
that participate as AnOperation() in solutions that apply the Factory Method pat-
tern are often template methods that, among others, call factory methods.
Adapter
Both the Adapter pattern and the Template Method pattern provides an interface
through which operations that are implemented in other classes are called. The
difference is that Adapter provides an interface to access non-complying operations
that cannot be changed while the operations accessed through the template method
is expected to comply and are most likely to change.
Builder
Both Builder and the Template Method pattern require a process to be encapsulated
in a method. In fact the method that has to be implemented by the concrete builders
to assemble a product is a template method.
3.5 Example
10
Figure 4 is a class diagram of an application that implements the Template Method
pattern. It is based on the example of a an application of the Template Method pattern
by [10]. The participants are as follows:
AbstractClass
ConcreteClass
• This example has two concrete classes named Monopoly and Chess. Each
of these classes implements the defined primitive operations to carry out the
subclass-specific steps of the algorithm which is different for each game.
3.6 Exercises
1. Figure 5 is a UML class diagram showing classes called Cow, Pig, Animal and Goat.
These classes are part of the implementation of a strategy game in which the player
is required to run a farm as profitable as possible. It is an implementation of the
Template Method Pattern.
2. Assume a class called Secretary that is derived from the Employee class have
been added to the system described in Section 3.2.2. Further, assume the following
methods are implemented respectively in the Manager class and the Secretary class:
void Manager : : workDay ( )
{
cout << ” a r r i v e ” << e n d l ;
cout << ” d r i n k c o f f e e ” << e n d l ;
11
Figure 5: Animal class implementing a template method
void S e c r a t a r y : : workDay ( )
{
cout << ” a r r i v e ” << e n d l ;
cout << ” d r i n k c o f f e e ” << e n d l ;
cout << ” check c a l e n d a r ” << e n d l ;
cout << ” t a k e minutes o f m e e t i n g s ” << e n d l ;
cout << ” t a k e lunch break ” << e n d l ;
cout << ” a r r a n g e venues and c a t e r i n g f o r m e e t i n g s ” << e n d l ;
cout << ” go home” << e n d l ;
}
• code a template method in the Employee class that describes the basic algo-
rithm of a work day for both these classes in steps that describe the flow in
steps separating the invariant sections from the variant sections
• define primitive operation methods for each of these steps and implement them
in the appropriate classes.
3. Implement the selection sort algorithm to sort an array of objects of unknown type
as a template method. Implement concrete classes for two different types of objects,
for example integers and strings, with implementations for the abstract methods you
had to defined and used in your template method. Add another concrete class that
extends your abstract class for yet another type of object that can be sorted by the
12
algorithm in your template method, for example triangles which are compared in
terms of their areas.
References
[1] Martin Fowler. Refactoring: Improving the Design of Existing Code. Addison-Wesley,
Reading, Mass, 1999.
[2] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design patterns :
elements of reusable object-oriented software. Addison-Wesley, Reading, Mass, 1995.
[4] Scott Meyers. Effective C++: 55 specific ways to improve your programs and designs.
Pearson Education Inc, Upper Saddle River, NJ 074548, 3rd edition, 2008.
[8] Herb Sutter. Sutter’s mill: virtuality. C/C++ Users Journal - Graphics, 19:53 – 58,
September 2001. ISSN 1075-2838.
[9] Richard E. Sweet. The mesa programming environment. ACM SIGPLAN Notices,
20:216–229, June 1985. ISSN 0362-1340.
13