Title: ....and other creepy things from John Vlissides
1....and other creepy things from John Vlissides
2The Visitor Pattern EXISTS!
- And its INTENT is to represent an operation to be
performed on the elements of an object structure.
3How?
- By letting the user define a new operation
without changing the classes of the elements on
which it operates!
4Motivation
- Consider a compiler with abstract syntax trees...
5Abstract Syntax Trees
- Compiler may need to define
- operations for
-
- Type-Checking
- Code Optimization
- Flow Analysis
- Variable Checking
- ...and more!
6Meaning....
- There will be one class for every single thing
that needs to be performed... - Distributing operations amongst various node
classes is hard to understand, maintain and
change! - Adding a new operation would be a pain in the butt
7What we want...
- Each new operation should be added separately
- All of the node classes to be independent of
their operations
8The Solution
- Package related operations from each class in a
separate object, and pass it to elements of the
abstract syntax tree as it is traversed. - We call this object...
9On a serious note
- When an element accepts a visitor, it sends a
request to it that encodes the elements class. - It also includes the element as an argument.
- The visitor is left to execute the operation for
that element, which used to be in the class of
the element.
10This is important too
- To make visitors work for more than just
type-checking, we need an abstract parent
NodeVisitor class for all visitors of an abstract
syntax tree.
11NodeVisitor
- NodeVisitor must declare an operation for each
node class.
12Visitor Up Close and Personal
- There are two class hierarchies with this pattern
(page 332 333) -
- Node - for elements being operated on
- NodeVisitor - for the visitors that define
operations on the elements
13Visitor, continued
- A new operation is created by adding a new
subclass in the visitors class hierarchy. - New functionality can simply be added by defining
new NodeVisitor subclasses.
14You know you wanna use this 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. - Many distinct and unrelated operations need to be
performed on objects in an object structure and
you dont want to pollute their classes with
these operations. - The classes defining the object structure rarely
change, but you often want to define new
operations over the structure. -
15(No Transcript)
16Participants
- Visitor declares a visit operation for each
class of ConcreteElement in the object structure - ConcreteVisitor (PriceVisitor) implements each
operation declared by Visitor - Element (Trash) defines an Accept operation
that takes a visitor as an argument
17More Participants!
- ConcreteElement (Aluminum, Paper, Glass)
implements an Accept operation that takes a
visitor as an argument - ObjectStructure (next to Trash)
- - can enumerate its elements
- - may provide a high-level interface to allow
the visitor to visit its elements - - may be a composite or a collection like a
set or list.
18Collaborations
- A client that uses Visitor must create a
ConcreteVisitor object and then traverse the
object structure, visiting each element with the
visitor (page 335) - 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.
19Consequences
- 1. Visitor makes adding new operations easy!
- 2. A Visitor gathers related operations and
separates unrelated ones, simplifying classes
defining elements and algorithms defined by
visitors. - 3. Adding new ConcreteElement classes is hard.
- 4. Visitor does not have access restrictions
like an iterator does. It can visit objects that
dont have a common parent class, and you can add
any type to a visitor interface.
5. Visitors can accumulate state as they visit
each element in the object structure.
6. The Visitor pattern often forces you to
provide public operations that access an
elements internal state, which may compromise
encapsulation.
20The Implementation
21Technical Details
- Double Dispatch Visitor uses this to let us add
operations to classes without changing them. Not
all programming languages support it directly
(like C). - It means that operations get executed depending
on the kind of request and types of two
receivers, NOT one.
22This is Crucial!
- Because of double dispatch, an executed operation
depends on the type of Visitor and the Element it
visits. - Binding operations can be done at run-time with
Accept in lieu of statically with the element
interface.
23And who is responsible
- ...for object structure traversal?
- After all, we know that a visitor must visit
- each element of the object structure.
24Hmmm......
- Responsibility can fall on
- 1) the structure,
- 2) the visitor, or
- 3) a separate iterator
- Most common is to use the structure itself, but
an iterator is used just as effectively. - The visitor is used least often to do it, because
traversal code often gets duplicated.
25Usage
- Visitor is not used often, at least according to
www.dofactory.com and www.nice.sourceforge.net/vis
itor.html - The Second site considers it totally useless.
- But dont let that discourage you, because its a
cool pattern.
26And lastly...
- Visitor can be used to apply an operation over an
object structure defined by the composite
pattern. - Visitor can also do the interpretation for the
Interpreter pattern.
27Onto Vlissides!
28Visiting Rights
- So far weve used Composite and Proxy for
supporting symbolic links. - See Figure 2.3, page 29
- Composite contributed Node, File and Directory
classes - Proxy contributed the Link class.
29Alexandrian Density
- The Node class is the Component in
- the COMPOSITE pattern and the
- Subject in the PROXY pattern.
- Christopher Alexander (above) called
- this density.
- So he got the term named after him.
- Lucky guy.
30Our File System
- The Node Interface is up for
- discussion
- We want a minimal set of operations that lets
clients build open-ended functionality. - Performing surgery on the interface would be a
hassle every time we wanted to add something new
to it.
31Is there an alternative?
- What if we take functionality out of the node
classes and put it into a client? - We need Downcasts to do this, making the client
complicated.
32But Downcasts are yucky!
- Dynamic_castltFilegt(node)
33Visitor...TO THE RESCUE!
- Our file system problem is similar to the
abstract syntax tree example - By using the accept method like we did before, we
let the visitor pattern do the work for us. - Bottom line No type tests or downcasting
34More on this
- Once we establish visiting rights by adding
accept(Visitor ) to Node classes, those classes
NEVER need to be modified again. - Vlissides uses function overloading, but encoding
the type of Node in the visit operations name
works just as well (page 35-36)
35Is the Visitor right for you?
- The Visitor pattern isnt
- for everyone. Consult
- your textbook to find out
- if its the pattern that
- youre looking for.
36Things to Ask Yourself
- Is the class hierarchy Im visiting stable? Or
will it be changing like crazy? - Adding a new kind of Node may force us to
change all the classes in the Visitor hierarchy
just to add a corresponding visit operation.
- Will the circular dependency between Visitor and
Node class hierarchies bother you? - A change to either base class interface is
likely to prompt a recompile of both hierarchies.
37Kevlin Henney The guy who was referenced on Page
37
- C Overloading does not
- require having to overload all
- versions of visit or that you
- abandon overloading the visit
- member.
38Valuable Insight
- The using declaration allows us to inject names
from a base class into a class for overloading. - This maintains overloading regularity.
- And its noninvasive because users are not forced
to remember names or conventions from the visit
function.
39Up Next Security
- 1) Protecting the system from inadvertent and
malicious corruption - 2) Maintaining system integrity in the face of
hardware and software errors.
40Any Questions?
- Manne or Nick would love to answer them.
41Credits
Patterns Mentioned Visitor Composite Proxy Inter
preter
Good TAs Chris Swope Yuling Liang
Inspiration Provided By The Nick Yianilos
Design Pattern Experience
- The Gang
- Erich Gamma
- Richard Helm
- Ralph Johnson
- John Vlissides
Thanks For Watching CSE 432
Good Teacher Chris Gill
- References
- Christopher Alexander
- Kevlin Henney