This page covers two behavioral design patterns from the Gang of Four. Template Method defines the skeleton of an algorithm in a base class, deferring specific steps to subclasses. Visitor represents an operation to be performed on elements of an object structure, allowing new operations without modifying element classes. Both patterns manage the tension between fixed structure and variable behavior, but at different granularities.
Template Method:
Visitor:
Template Method — Hook pattern:
// Parent controls extension via hook
void ParentClass::Operation() {
// ParentClass behavior
HookOperation(); // subclass extension point
}
void ParentClass::HookOperation() { } // default: no-op
void DerivedClass::HookOperation() {
// derived class extension
}
Template Method — View invariant example:
void View::Display() {
SetFocus(); // concrete operation (setup)
DoDisplay(); // hook operation (subclass overrides)
ResetFocus(); // concrete operation (cleanup)
}
Visitor — Accept/Visit protocol:
class Visitor {
public:
virtual void VisitElementA(ElementA*);
virtual void VisitElementB(ElementB*);
protected:
Visitor();
};
class ElementA : public Element {
public:
virtual void Accept(Visitor& v) { v.VisitElementA(this); }
};
Visitor — Composite traversal:
void Chassis::Accept(EquipmentVisitor& visitor) {
for (ListIterator<Equipment*> i(_parts); !i.IsDone(); i.Next()) {
i.CurrentItem()->Accept(visitor); // recurse children first
}
visitor.VisitChassis(this); // then visit self
}
Visitor — Client usage:
Equipment* component;
InventoryVisitor visitor;
component->Accept(visitor);
cout << visitor.GetInventory();
1. Template Method is about *inheritance-based algorithm customization*; the invariant structure stays in the parent, variable steps are overridden in subclasses
2. Hook operations provide default (often empty) behavior and *may* be overridden; primitive operations are abstract and *must* be overridden — know the difference
3. The Hollywood Principle ("Don't call us, we'll call you") is the defining characteristic of Template Method's inverted control
4. In C++, make the template method non-virtual (cannot be overridden) and primitive operations protected pure virtual
5. Minimize primitive operations — fewer required overrides = easier subclassing
6. Visitor's key tradeoff: easy to add operations, hard to add element types (inverse of standard polymorphism)
7. Double dispatch is the mechanism that makes Visitor work — Accept dispatches on element type, then the Visit call dispatches on visitor type
8. Visitor is appropriate when the element class hierarchy is stable but operations change frequently; if elements change often, put operations in the element classes instead
9. Visitor can accumulate state during traversal (e.g., PricingVisitor accumulates total cost)
10. Three options for traversal responsibility: the object structure (most common), the visitor (for complex/irregular traversals), or a separate iterator
11. Visitor breaks encapsulation — elements must expose enough interface for visitors to work, which may reveal internal state
12. Unlike iterators, visitors can operate on objects without a common parent class