Date post: | 04-Jan-2016 |
Category: |
Documents |
Upload: | barbra-jones |
View: | 213 times |
Download: | 0 times |
....and other creepy things from John Vlissides
The Visitor Pattern EXISTS!The Visitor Pattern EXISTS!
And its And its INTENTINTENT is to represent an is to represent an operation to be performed on the elements operation to be performed on the elements of an object structure. of an object structure.
How?How?
By letting the user define a new operation By letting the user define a new operation without changing the classes of the without changing the classes of the elements on which it operates!elements on which it operates!
MotivationMotivation
Consider a compiler with abstract Consider a compiler with abstract syntax trees...syntax trees...
Abstract Syntax TreesAbstract Syntax Trees
Compiler may need to define Compiler may need to define operations for:operations for:
Type-CheckingType-CheckingCode OptimizationCode OptimizationFlow AnalysisFlow AnalysisVariable CheckingVariable Checking...and more!...and more!
Meaning....Meaning....
There will be one class for every single There will be one class for every single thing that needs to be performed...thing that needs to be performed...
Distributing operations amongst various Distributing operations amongst various node classes is hard to understand, node classes is hard to understand, maintain and change! maintain and change!
Adding a Adding a newnew operation would be a pain in operation would be a pain in the buttthe butt
What we want...What we want...
Each new operation should be added Each new operation should be added separatelyseparately
All of the node classes to be independent All of the node classes to be independent of their operationsof their operations
The SolutionThe Solution Package related operations from each class in a Package related operations from each class in a
separate object, and pass it to elements of the separate object, and pass it to elements of the abstract syntax tree as it is traversed.abstract syntax tree as it is traversed.
We call this object...We call this object...
On a serious noteOn a serious note
When an element accepts a visitor, it sends a When an element accepts a visitor, it sends a request to it that encodes the element’s class. request to it that encodes the element’s class.
It also includes the element as an argument.It also includes the element as an argument.
The visitor is left to execute the operation for that The visitor is left to execute the operation for that element, which used to be in the class of the element, which used to be in the class of the element.element.
This is important tooThis is important too
To make visitors work for more than just To make visitors work for more than just type-checking, we need an type-checking, we need an abstract abstract parent NodeVisitor classparent NodeVisitor class for all visitors of for all visitors of an abstract syntax tree.an abstract syntax tree.
NodeVisitorNodeVisitor
NodeVisitor must declare an operation for NodeVisitor must declare an operation for each node class.each node class.
Visitor – Up Close and PersonalVisitor – Up Close and Personal
There are two class hierarchies with this There are two class hierarchies with this pattern (page 332 – 333): pattern (page 332 – 333):
NodeNode - for elements being operated - for elements being operated onon
NodeVisitorNodeVisitor - for the visitors that - for the visitors that define define operations on the elementsoperations on the elements
Visitor, continuedVisitor, continued
A new operation is created by adding a A new operation is created by adding a new subclass in the visitors class new subclass in the visitors class hierarchy.hierarchy.
New functionality can simply be added by New functionality can simply be added by defining new NodeVisitor subclasses.defining new NodeVisitor subclasses.
You know you wanna use this when...You know you wanna use this when...
1)1) An object structure contains many classes of objects An object structure contains many classes of objects with differing interfaces, and you want to perform with differing interfaces, and you want to perform operations on these objects that depend on their operations on these objects that depend on their concrete classes.concrete classes.
2)2) Many distinct and unrelated operations need to be Many distinct and unrelated operations need to be performed on objects in an object structure and you performed on objects in an object structure and you don’t want to “pollute” their classes with these don’t want to “pollute” their classes with these operations.operations.
3)3) The classes defining the object structure rarely The classes defining the object structure rarely change, but you often want to define new operations change, but you often want to define new operations over the structure.over the structure.
ParticipantsParticipants
VisitorVisitor – declares a visit operation for each – declares a visit operation for each class of ConcreteElement in the object structureclass of ConcreteElement in the object structure
ConcreteVisitorConcreteVisitor (PriceVisitor) – implements (PriceVisitor) – implements each operation declared by Visitoreach operation declared by Visitor
ElementElement (Trash) – defines an Accept operation (Trash) – defines an Accept operation that takes a visitor as an argumentthat takes a visitor as an argument
More Participants!More Participants!
ConcreteElementConcreteElement (Aluminum, Paper, Glass) – (Aluminum, Paper, Glass) – implements an Accept operation that takes a visitor as implements an Accept operation that takes a visitor as an argumentan argument
ObjectStructureObjectStructure (next to Trash) (next to Trash) - can enumerate its elements - can enumerate its elements - may provide a high-level interface to allow the - may provide a high-level interface to allow the visitor to visit its elements visitor to visit its elements - may be a composite or a collection like a set or - may be a composite or a collection like a set or list. list.
CollaborationsCollaborations
A client that uses Visitor must create a A client that uses Visitor must create a ConcreteVisitor object and then traverse the ConcreteVisitor object and then traverse the object structure, visiting each element with the object structure, visiting each element with the visitor (page 335)visitor (page 335)
When an element is visited, it calls the visitor When an element is visited, it calls the visitor operation that corresponds to its class. The operation that corresponds to its class. The element supplies itself as an argument to this element supplies itself as an argument to this operation to let the visitor access its state, if operation to let the visitor access its state, if necessary.necessary.
ConsequencesConsequences
11. Visitor makes adding new operations easy!. Visitor makes adding new operations easy!2.2. A Visitor gathers related operations and A Visitor gathers related operations and
separates unrelated ones, simplifying classes separates unrelated ones, simplifying classes defining elements and algorithms defined by defining elements and algorithms defined by visitors.visitors.
3.3. Adding new ConcreteElement classes is hard. Adding new ConcreteElement classes is hard.4.4. Visitor does not have access restrictions like Visitor does not have access restrictions like
an iterator does. It can visit objects that don’t an iterator does. It can visit objects that don’t have a common parent class, and you can add have a common parent class, and you can add any type to a visitor interface.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 element’s internal state, which may compromise encapsulation.
The ImplementationThe Implementation
IIs on page 337.s on page 337.
Technical DetailsTechnical Details
Double Dispatch – Double Dispatch – Visitor uses this to let Visitor uses this to let us add operations to classes without us add operations to classes without changing them. Not all programming changing them. Not all programming languages support it directly (like C++).languages support it directly (like C++).
It means that operations get executed It means that operations get executed depending on the kind of request and depending on the kind of request and types of types of twotwo receivers, NOT one. receivers, NOT one.
This is Crucial!This is Crucial!
Because of double dispatch, an executed Because of double dispatch, an executed operation depends on the type of Visitor operation depends on the type of Visitor and the Element it visits.and the Element it visits.
Binding operations can be done at run-Binding operations can be done at run-time with “Accept” in lieu of statically with time with “Accept” in lieu of statically with the element interface.the element interface.
And who is responsibleAnd who is responsible
...for object structure traversal?...for object structure traversal?
After all, we know that a visitor must visitAfter all, we know that a visitor must visiteach element of the object structure.each element of the object structure.
Hmmm......Hmmm......
Responsibility can fall on: Responsibility can fall on: 1) the structure, 1) the structure, 2) the visitor, or 2) the visitor, or 3) a separate iterator3) a separate iterator
Most common is to use the structure itself, but Most common is to use the structure itself, but an iterator is used just as effectively.an iterator is used just as effectively.
The visitor is used least often to do it, because The visitor is used least often to do it, because traversal code often gets duplicated.traversal code often gets duplicated.
UsageUsage
Visitor is not used often, at least according Visitor is not used often, at least according to to www.dofactory.comwww.dofactory.com and and www.nice.sourceforge.net/visitor.htmlwww.nice.sourceforge.net/visitor.html
The Second site considers it totally The Second site considers it totally useless.useless.
But don’t let that discourage you, because But don’t let that discourage you, because it’s a cool pattern.it’s a cool pattern.
And lastly...And lastly...
Visitor can be used to apply an operation Visitor can be used to apply an operation over an object structure defined by the over an object structure defined by the composite pattern.composite pattern.
Visitor can also do the interpretation for Visitor can also do the interpretation for the Interpreter pattern.the Interpreter pattern.
Onto Vlissides!Onto Vlissides!
Visiting RightsVisiting Rights
So far we’ve used So far we’ve used CompositeComposite and and ProxyProxy for for supporting symbolic links.supporting symbolic links.
See Figure 2.3, page 29See Figure 2.3, page 29
Composite contributed Node, File and Directory Composite contributed Node, File and Directory classesclasses
Proxy contributed the Link class.Proxy contributed the Link class.
Alexandrian DensityAlexandrian Density
The Node class is the Component in The Node class is the Component in the COMPOSITE pattern and the the COMPOSITE pattern and the Subject in the PROXY pattern. Subject in the PROXY pattern.
Christopher Alexander (above) called Christopher Alexander (above) called this “density”.this “density”.
So he got the term named after him.So he got the term named after him.
Lucky guy.Lucky guy.
Our File SystemOur File System
The Node Interface is up for The Node Interface is up for discussiondiscussion
We want a minimal set of operations that We want a minimal set of operations that lets clients build open-ended functionality.lets clients build open-ended functionality.
““Performing surgery” on the interface Performing surgery” on the interface would be a hassle every time we wanted would be a hassle every time we wanted to add something new to it.to add something new to it.
Is there an alternative?Is there an alternative?
What if we take functionality out of the What if we take functionality out of the node classes and put it into a client?node classes and put it into a client?
We need Downcasts to do this, making the We need Downcasts to do this, making the client complicated.client complicated.
But Downcasts are yucky!But Downcasts are yucky!
Dynamic_cast<File*>(node)Dynamic_cast<File*>(node)
Visitor...TO THE RESCUE!Visitor...TO THE RESCUE!
Our file system problem is similar to the Our file system problem is similar to the abstract syntax tree exampleabstract syntax tree example
By using the accept method like we did By using the accept method like we did before, we let the visitor pattern do the before, we let the visitor pattern do the work for us.work for us.
Bottom line: No type tests or downcastingBottom line: No type tests or downcasting
More on thisMore on this
Once we establish visiting rights by adding Once we establish visiting rights by adding accept(Visitor &) to Node classes, those accept(Visitor &) to Node classes, those classes NEVER need to be modified classes NEVER need to be modified again.again.
Vlissides uses function overloading, but Vlissides uses function overloading, but encoding the type of Node in the visit encoding the type of Node in the visit operation’s name works just as well (page operation’s name works just as well (page 35-36)35-36)
Is the Visitor right for you?Is the Visitor right for you?
The Visitor pattern isn’t The Visitor pattern isn’t
for everyone. Consult for everyone. Consult
your textbook to find out your textbook to find out
if it’s the pattern that if it’s the pattern that
you’re looking for.you’re looking for.
Things to Ask YourselfThings to Ask Yourself
Is the class hierarchy I’m visiting stable? Is the class hierarchy I’m visiting stable? Or will it be changing like crazy?Or will it be changing like crazy?
““Adding a new kind of Node may force us Adding a new kind of Node may force us to change all the classes in the Visitor to change all the classes in the Visitor hierarchy just to add a corresponding visit hierarchy just to add a corresponding visit operation.”operation.”
Will the circular dependency between Will the circular dependency between Visitor and Node class hierarchies bother Visitor and Node class hierarchies bother you?you?
A change to either base class interface is A change to either base class interface is likely to prompt a recompile of both likely to prompt a recompile of both hierarchies.hierarchies.
Kevlin Henney: The guy who was Kevlin Henney: The guy who was referenced on Page 37referenced on Page 37
““C++ Overloading does not C++ Overloading does not
require having to overload allrequire having to overload all
versions of versions of visitvisit or that you or that you
abandon overloading the abandon overloading the visit visit
member.”member.”
Valuable InsightValuable Insight
The “using” declaration allows us to inject The “using” declaration allows us to inject names from a base class into a class for names from a base class into a class for overloading.overloading.
This maintains overloading regularity.This maintains overloading regularity.
And it’s noninvasive because users are And it’s noninvasive because users are not forced to remember names or not forced to remember names or conventions from the conventions from the visit visit function.function.
Up Next: SecurityUp Next: Security
1) Protecting the system from inadvertent 1) Protecting the system from inadvertent and malicious corruptionand malicious corruption
2) Maintaining system integrity in the face 2) Maintaining system integrity in the face of hardware and software errors. of hardware and software errors.
Any Questions?Any Questions?
ManneManne or or NickNick would love to would love to answer them.answer them.
CreditsCredits
The “Gang”:The “Gang”:Erich GammaErich GammaRichard HelmRichard Helm
Ralph JohnsonRalph JohnsonJohn VlissidesJohn Vlissides
References:References:Christopher AlexanderChristopher Alexander
Kevlin HenneyKevlin Henney
Patterns Mentioned:Patterns Mentioned:VisitorVisitor
CompositeCompositeProxyProxy
InterpreterInterpreter
Thanks For Watching:Thanks For Watching:CSE 432CSE 432
Inspiration Provided By:Inspiration Provided By:
The Nick Yianilos Design The Nick Yianilos Design Pattern ExperiencePattern Experience
Good Teacher:Good Teacher:Chris GillChris Gill
Good TA’s:Good TA’s:Chris SwopeChris SwopeYuling Liang Yuling Liang