Visitor Design Pattern
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates. (dofactory)
- Visitor declares a Visit operation for each class of ConcreteElement in the object structure. The operation's name and signature identifies the class that sends the Visit request to the visitor. That lets the visitor determine the concrete class of the element being visited. Then the visitor can access the elements directly through its particular interface
- ConcreteVisitor implements each operation declared by Visitor. Each operation implements a fragment of the algorithm defined for the corresponding class or object in the structure. ConcreteVisitor provides the context for the algorithm and stores its local state. This state often accumulates results during the traversal of the structure.
- Element defines an Accept operation that takes a visitor as an argument and ConcreteElement implements the Accept operation that takes a visitor as an argument.
- ObjectStructure can enumerate its elements or may provide a high-level interface to allow the visitor to visit its elements or may either be a Composite (pattern) or a collection such as a list or a set
- A client that uses the Visitor pattern must create a ConcreteVisitor object and then traverse the object structure, visiting each element with the visitor.
- When an element is visited, it calls the Visitor operation that corresponds to its class. The element supplies itself as an argument to this operation to let the visitor access its state, if necessary.
- Similar operations have to be performed on objects of different types grouped in a structure (a collection or a more complex structure). The object structure is not likely to be changed but is very probable to have new operations which have to be added. Since the pattern separates the visitor (representing operations, algorithms, behaviors) from the object structure it's very easy to add new visitors as long as the structure remains unchanged.
- Do the right thing based on the type of two objects.
- Visitor lets you define a new operation without changing the classes of the elements on which it operates.
- The Visitor pattern is the classic technique for recovering lost type information without resorting to dynamic casts.
- Double dispatch - In “double dispatch”, the operation executed depends on: the name of the request, and the type of TWO receivers (the type of the Visitor and the type of the element it visits).
- Visitor is not good for the situation where “visited” classes are not stable. Every time a new Composite hierarchy derived class is added, every Visitor derived class must be amended.
- The visitor methods signature has to be known in advance.
- A lot of code has to be written to prepare the use of visitors
- If the hierarchy, ObjectStructure, cannot be modified because you are not allowed to, the visitor pattern cannot be applied at all.
- You may be forced to compromise encapsulation, by needing to expose too much of the Element class's internals to make the Element classes "visitor ready"
- If overused it can increase undesirable coupling within our application, versus a solution where we just used polymorphism; ie. the Elements descend from an Abstract base class, and each Element overriding the operation" methods.
- Data accumulated by walking the tree has to be stored on the visitor.
Classic implementation of visitor pattern sample
Visitor pattern sample using C# 4.0 dynamic
- Iterator pattern defines a traversal principle without making a type differentiation within the traversed objects.
- Command pattern encapsulates like the visitor pattern one or more functions in an object to present them to a caller. Unlike the visitor, the command pattern does not enclose a principle to traverse the object structure. Hence, the Visitor pattern is like a more powerful Command pattern because the visitor may initiate whatever is appropriate for the kind of object it encounters.
- The visitor pattern can be used in addition with the Composite pattern. The object structure can be a composite structure. In this case in the implementation of the accept method of the composite object the accept methods of the component object has to be invoked.