Outline • Generic Implementation – Visitor classes – Visited classes – Visitable macro • UML Design – Use cases – Class diagram – Sequence diagram 7/1/2016 CS 631: Visitor Implementation 1 The Generic Implementation • BaseVisitable – The root of all hierarchies that can be visited • Visitable – A mix-in class that converts visitable properties to a class in visitable hierarchy • BaseVisitor – The root of the visitor hierarchy • Visitor – A mix-in class that confers visitor properties to a class in the visitor hierarchy 7/1/2016 CS 631: Visitor Implementation 2 Generic Implementation: Visitor Classes // The strawman class class BaseVisitor { public: virtual ~TraderVisitor() {} }; // Class to define a pure virtual function for // visiting an object of type T and return type R template <class T, typename R = void> class Visitor { public: typedef R ReturnType virtual ReturnType visit(T&) = 0; } 7/1/2016 CS 631: Visitor Implementation 3 Generic Implementation: Concrete Visitor class DealEvaluator : public class BaseVisitor, // required public class Visitor<Hedger>, public class Visitor<Speculator>, public class Visitor<Arbitrageur> { public: void visit(Hedger &); void visit(Speculator&); void visit(Arbitrageur&); }; 7/1/2016 CS 631: Visitor Implementation 4 Generic Implementation: Base Visited Class // The base visitable class to define accept() template <typename R=void> class BaseVisitable { public: typedef R ReturnType; virtual ~BaseVisitable() {} virtual ReturnType accept(BaseVisitor&) = 0; }; // The challenge is to provide a library // implementation for concrete accept() functions 7/1/2016 CS 631: Visitor Implementation 5 Generic Implementation: Visitable Macro #define DEFINE_VISITABLE() \ virtual ReturnType accept(BaseVisitor& guest) \ {return acceptImpl(*this, guest);} template <typename R=void> class BaseVisitable { public: ... typedef R ReturnType; virtual ~BaseVisitable() {} virtual ReturnType accept(BaseVisitor&) = 0; 7/1/2016 CS 631: Visitor Implementation 6 Generic Implementation: Visitable Macro (cont.) // class BaseVisitable ... protected: // Give access only to hierarchy ... template <class T> static ReturnType acceptImpl (T& visited, BaseVisitor& guest) { // Acyclic visitor if (Visitor<T>* p = dynamic_cast<Visitor<T>* (&guest)) return p->visit(visited); return ReturnType(); } 7/1/2016 CS 631: Visitor Implementation 7 Generic Implementation: Concrete Visited Classes class Trader : public class BaseVisitable<> { public: DEFINE_VISITABLE() ... }; class Hedger : public class Trader { public: DEFINE_VISITABLE() ... } 7/1/2016 CS 631: Visitor Implementation 8 Generic Implementation: Concrete Visited Classes class DealEvaluator : public class BaseVisitor, // required public class Visitor<Trader>, // visits Trader public class Visitor<Hedger>, // visits Hedger ... { public: void visit(Trader&) {...} void visit(Hedger&) {...} ... }; int main() { DealEvaluator eval; Trader trader = new Hedger(); trader->accept(eval); } 7/1/2016 CS 631: Visitor Implementation 9 Generic Implementation: Summary • Derive the root of your hierarchy from BaseVisitable<YourReturnType> • Add to each class (Trader, Hedger) in the visitable hierarchy the DEFINE_VISITABLE macro. – The hierarchy is ready to be visited with no dependency on any Visitor class! • Derive each concrete Visitor (TraderVisitor, DealMaker, ...) from BaseVisitor. Also derive it from all concrete visitable classes X: Visitor<X,YourReturnType> • The client code and dependencies are reduced to the bare necessity. 7/1/2016 CS 631: Visitor Implementation 10 Market Simulator: Use Case Diagram 7/1/2016 CS 631: Visitor Implementation 11 Visitor Pattern: Class Diagram 7/1/2016 CS 631: Visitor Implementation 12 Visitor Pattern: Sequence Diagram 7/1/2016 CS 631: Visitor Implementation 13 Visitor Pattern: Summary • Visitor makes adding new operation easy. – Adding a new operation means adding a new visitor. • A visitor gathers related operations and separates unrelated ones. – Related behavior is localized in a visitor. – Unrelated sets of behavior are partitioned in their own visitor subclasses. • Adding new ConcreteElement classes is hard. – Each new class results in adding methods to the Visitor hierarchy. – Element hierarchy needs to be stable! 7/1/2016 CS 631: Visitor Implementation 14 Summary (cont.) • Visiting across class hierarchies. – Any type of object can be added to a Visitor interface: • visitMyType(MyType&); visitYourType(YourType&) • Accumulating state. – Visitors can accumulate state as they visit each element in the object structure. • Breaking encapsulation. – Assumes the ConcreteElement interface is powerful enough to let visitors do their job. – The pattern often forces to expose more public interface. 7/1/2016 CS 631: Visitor Implementation 15