|
CS 635: Advanced Object-Oriented Design & Programming |
|
---|
Spring Semester, 1998
Visitor
To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 28-Apr-98
Contents of Doc 27, Visitor
CS 635 Doc 27 Visitor
References | slide # 1 |
| |
Visitor | slide # 2 |
...Structure | slide # 2 |
...Example - Tree Structure | slide # 3 |
...When to Use Visitor | slide # 6 |
...Consequences | slide # 6 |
...Variations | slide # 8 |
......Use Function Overloading | slide # 8 |
......ExtrinsicVisitor | slide # 9 |
References
Design Patterns: Elements of Resuable Object-Oriented
Software, Gamma, Helm, Johnson, Vlissides, Addison-Wesley,
1995, pp 331-344
"Default and Extrinsic Visitor", Martin E. Nordberg III, in Pattern
Languages of Program Design 3, Edited by Martin,
Riehle, Buschmmann, Addison-Wesley, 1998, pp 105-123
"Acyclic Visitor", Robert C. Martin, in Pattern Languages of
Program Design 3, Edited by Martin,
Riehle, Buschmmann, Addison-Wesley, 1998, pp 94-104
Visitor
Structure
Example - Tree Structure
What about preorder visit, postorder visit?
What about an HTML print?
What about printing a 2D representation?
What if this was an expression tree - evaluation?
What if this was a binary search tree - adding, deleting
What about balancing the binary search tree -
- AVL
- Red-Black
Solution 1
Build all the operations into the tree structure
This works in many situations
If you need to add a lot of operations the classes can become
cluttered
Solution 2
- Put operations into separate object (pseudo-visitor)
- Iterate through the structure
- Pass each element in the structure to operations object
- Operation object processes each element
This helps avoid the clutter of the classes used in the structure
This works in situations where solution 1 does not
Iteration may be difficult to do, it might be easier to let the
structure to the traversal
When the structure contains objects of different types using just
iteration can be a problem
The iterator has to be able to return different possible unrelated
types, which may not be possible (C++) or difficult
Operation objects can be passed elements it is not designed to
handle
Solution 3
- Put operations into separate object
- Pass the operations object (visitor) to each element in the
structure
- The element then calls the proper method in visitor for its
type
- Operation object processes each element properly
This is more complex than solutions 1 & 2
The traversal can be done by the structure, an iterator, or the
visitor
- Usually the traversal is done by the structure
- Having the traversal in the visitor can lead to duplicated code
The visitor is told what type it is acting on, so using the wrong
visitor will be a compile error
When to Use Visitor
- When an object structure contains many classes of objects
with differing interfaces, and you want to perform operations on
these objects that depend on their concrete classes
- When many distinct and unrelated operations need to be
preformed on objects in an object structure and you want to
avoid cluttering the classes with these operations
- When the classes defining the structure rarely change, but
you often want to define new operations over the structure
Consequences
- Visitors makes adding new operations easier
- If the structure involves many different classes then adding
a new operation to the structure requires changing all those
classes
- Visitors gathers related operations, separates unrelated ones
- A print visitor could have all the different ways to print
Consequences Continued
- Adding new ConcreteElement classes is hard
- To add a new ConcreteElement you need to change all
existing visitors
- Visiting across class hierarchies
- Text claims iterators can not iterate through structure
containing unrelated classes
- However, the visitor assumes that each element in the
structure contains a visit method, which implies at least a
common visit interface for all elements
- A visitor can accumulate information as it traverses the
structure
- The visitor may force you to provide public operations in the
elements that you would not otherwise make public
- C++ friends are useful here
Variations
Use Function Overloading
Overloading allows the accept method to be implemented once
in the Element class
ExtrinsicVisitor
The Visitor takes the responsibility of making sure a visitor can
visit a particular concrete element
Each Visitor knows which types of concrete classes it can visit
The canVisit method of each visitor returns true is that visitor
can visit that concrete type
New visitors can be created without changing the Element
classes
New Element classes can be added without having to change
old visitors
The above is slightly modified from the original ExtrinsicVisitor
pattern
In the original
- Element does not have an accept method
- The visit method of ExtrinsicVisitor does not call canVisit
- ObjectStructure calls canVisit to determine if an element can
be visited, then calls visit
- The visitElement methods are not over loaded
Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA
All rights reserved.
visitors since 28-Apr-98