GoF Template Method (pp. 325-330)
GoF Strategy (pp. 315-323)
PH Single User Protection (pp. 34-40)
Presentation by Julie Betlach
6/08/2009
1
GoF Template Method (pp. 325-330)
Template Method Pattern - Intent / Applicability
• Intent
– Define the skeleton of an algorithm, deferring some steps to
subclasses.
– Template Method lets subclasses redefine certain steps of an
algorithm, without changing the algorithm’s structure.
• Applicability – Use Template Method Pattern…
– To implement the invariant part of an algorithm, and leave it up to
subclasses to implement the part that can vary.
– When common code in subclasses should be factored and
localized in a common base class to avoid code duplication.
– To control extensions to subclasses. (Hook operations)
2
GoF Template Method (pp. 325-330)
Template Method Pattern - Participants
• AbstractClass
– Defines abstract primitive operations that concrete subclasses
define to implement steps of an algorithm.
– Implements a template method defining the skeleton of an
algorithm. It calls primitive operations as well as other
operations in the AbstractClass (or other classes).
• ConcreteClass
– Implements primitive
operations to carry out
subclass-specific steps
of the algorithm.
Note: Some concrete AbstractClass
methods can also be defined.
Hollywood Principle –
“Don’t call us, we’ll
call you.” => Parent
class calls operations
of subclass.
3
GoF Template Method (pp. 325-330)
Template Method Pattern - Participants
Template Method
Concrete
AbstractClass
Operation
void Application::OpenDocument (const char* name) {
if (!CanOpenDocument(name)) {
return;
PrimitiveOperation
}
Document* doc = DoCreateDocument();
if (doc) {
_docs->AddDocument(doc);
AboutToOpenDocument(doc);
doc->Open();
doc->DoRead();
}
}
Basic Algorithm
is the same for
all documents.
4
GoF Template Method (pp. 325-330)
Template Method Pattern - Implementation
Template Method – Don’t want this to be overridden,
so make it nonvirtual member function.
Concrete
AbstractClass
Operation
void Application::OpenDocument (const char* name) {
if (!CanOpenDocument(name)) {
return;
Primitive Operations
}
that must be
Document* doc = DoCreateDocument();
overridden (make
if (doc) {
these pure virtual in
_docs->AddDocument(doc);
abstract class).
AboutToOpenDocument(doc);
doc->Open();
Primitive Operation
doc->DoRead();
that has a default
}
behavior in
}
abstract class =
Hook operation.
Naming Convention suggestion is confusing.
Are DoCreateDocument and DoRead from the example called Template
Methods? I think book should have said that MacApp framework prefixes
primitive operation names with “Do”.
5
GoF Template Method (pp. 325-330)
Related Patterns
• Factory Methods – Are often called by template
methods. Example: Factory Method
DoCreateDocument is called by Template
Method OpenDocument.
• Strategy – Template Methods use inheritance to
vary part of an algorithm. Strategies use
delegation to vary the entire algorithm.
6
GoF Strategy (pp. 315-323)
Strategy Pattern - Intent / Applicability
• Intent
– Define a family of algorithms, encapsulate each one, and make
them interchangeable. Strategy lets the algorithm vary
independently from clients that use it.
• Applicability – Use Strategy Pattern when…
– Many related classes differ only in their behavior.
– You need different variants of an algorithm. For example,
defining different algorithms based on space-time tradeoffs.
– An algorithm uses data that a client shouldn’t know about.
– A class defines many behaviors, and these appear as multiple
conditional statements in its operations. Instead, move related
conditional branches into their own Strategy class.
7
GoF Strategy (pp. 315-323)
Strategy Pattern - Participants
• Strategy
– Declares an interface common to all supported algorithms. Context
uses this interface to call the algorithm defined by a ConcreteStrategy.
• ConcreteStrategy
– Implements the algorithm using the Strategy interface.
• Context
– Is configured with a ConcreteStrategy object
– Maintains a reference to a Strategy object
– May define an interface that lets Strategy access its data.
Picture & Example from: http://www.dofactory.com/Patterns/PatternStrategy.aspx
8
GoF Strategy (pp. 315-323)
Strategy Pattern - Participants
http://www.dofactory.com/Patterns/PatternStrategy.aspx
Show code in RealWorld Example
• Strategy
– SortStrategy
• ConcreteStrategy
– QuickSort
– ShellSort
– MergeSort
• Context
– SortedList
Picture & Example from: http://www.dofactory.com/Patterns/PatternStrategy.aspx
9
GoF Strategy (pp. 315-323)
Strategy Pattern – Consequences
• Good Consequences
– Good for families of related algorithms. Inheritance can help
factor out common functionality of algorithms.
– Alternative to subclassing which allows the developer to vary the
algorithm independent of its context.
– Strategies eliminate conditional statements.
– Provide different implementations of the same behavior.
Example: Sorting is goal, but many ways to sort.
• Drawbacks
– Clients must be aware of different strategies.
– Communication overhead between Strategy and Context – some
concrete strategies may not need all the parameters passed into
them.
– Increased number of objects. See Flyweight pattern for an
approach to solve this.
10
GoF Strategy (pp. 315-323)
Related Patterns
• Flyweight – Strategy objects often make good
flyweights.
11
PH Single User Protection (pp. 34-40)
Single User Protection
• Read Protection (do not reveal contents)
– Disallow streamOut
– Disallow getChild (makes sense if you consider
example of hiding the family tree information of a
person, where getChild returns the name of the
person’s descendents.)
• Write Protection (protect both attributes and
structure)
– Disallow streamIn, setName, adopt, orphan
– Treat setProtection carefully (explained in multi-user
section)
12
PH Single User Protection (pp. 34-40)
Single User Protection
• Write Protection (continued)
– Prevent deletion
• Can’t declare a node as a const in order to get compiler to
check this for us, because a node’s protection may change at
runtime.
• Instead, we can Protect the Destructor by putting it in the
Protected section.
– Don’t want to make it private because that wouldn’t let
subclasses extend the destructor to delete their children or any
other objects that they aggregate.
• We want a static member function (makes syntax nicer) and
we want the subclasses to be able to extend the definition.
13
PH Single User Protection (pp. 34-40)
Single User Protection
• Solution = Destroy() will be a Template Method!
class Node {
public:
static void destroy (Node*); // template method
protected:
virtual ~Node();
virtual bool isWriteable() = 0; // primitive operation
virtual void doWarning() = 0; // primitive operation
};
Because destroy is
void Node::destroy (Node* node) {
static, it can’t call Node
if (node->isWriteable()) {
operations directly.
delete node;
But it doesn’t need to
} else {
because it calls primitive
node->doWarning(undeletableWarning);
operations in the
}
subclasses.
}
Technically, isWriteable should start with “do” to be clear it is a primitive operation.
14
PH Single User Protection (pp. 34-40)
Single User Protection
class Node {
public:
static void destroy (Node*); // static template method
void streamOut (ostream& out); // non-static template method (also not virtual)
protected:
virtual ~Node();
virtual bool isWriteable() = 0; // primitive operation
virtual bool isReadable() = 0; // primitive operation
virtual void doWarning() = 0; // primitive operation
virtual void doStreamOut() = 0; // primitive operation
};
void Node::streamOut (ostream& out) {
if (isReadable()) {
doStreamOut();
} else {
doWarning(unreadableWarning);
}
}
However, if we define
another template method
which is not static, it is
allowed to call Node
functions, so it doesn’t
need the node passed in.
15
© Copyright 2026 Paperzz