the observer design patternblk/cs3667/extension... · the visitor design pattern •the visitor...
TRANSCRIPT
The Visitor Design Pattern
• the visitor design pattern is a way of separating an algorithm from an object structure upon which it operates.
• A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures.
• One creates a visitor class that implements all of the appropriate specializations of the virtual function.
• The visitor takes the instance reference as input, and implements the goal through double dispatch.
• In the GoF classification this is a behavioral design pattern
Acknowledgements
• Materials were borrowed from
– Design Patterns in Java by Steven Metsker and William Wake (textbook for course)
– Head First Design Patterns by Elisabeth Freeman, Eric Freeman, Bert Bates, and Kathy Sierra
– The compiler example was borrowed from lecture notes on Design Patterns by Brian Malloy at Clemson University
– The main bullets on the previous slide came from the wikipedia article on the Interpreter Pattern
Motivation• Consider a compiler that represents programs as abstract
syntax trees (ASTs)
• need to perform operations on ASTs
– type checking
– code generation
– printing
• One option: place all of these operations in the nodes of the AST
Node class hierarchy
Node
typeCheck()generateCode();prettyPrint();
VariableRefNode
typeCheck()generateCode();prettyPrint();
AssignmentNode
typeCheck()generateCode();prettyPrint();
Problem with Node class hierarchy
• Distributing operations across Node classes leads to a system that’s hard to understand, maintain and change.
• it’s confusing to have type-checking code in the same class with code to perform pretty printing.
• also, adding a new operation, e.g. data flow analysis, requires recompiling all of the classes!
Visitor• allows us to separate Node classes from operations “on”
Node classes
• allows each new operation to be added separately, withoutchanging Node class!
Nodes “accept” visitors
Node
accept(NodeVisitor)
VariableRefNode
accept(NodeVisitor)
AssignmentNode
accept(NodeVisitor v)
program
v.visitAssignment(this)
Visitor for Nodes
NodeVisitor
visitAssignment(node);visitVariableRef(node);
VariableRefNode
visitAssignment(node);visitVariableRef(node);
AssignmentNode
visitAssignment(node)visitVariableRef(node)
Visitor Pattern
• Define two class hierarchies
– one for elements being operated on (nodes)
– one for visitors that define operations on the elements
• create new operations by adding a new subclass to Visitor class hierarchy
Structure of Visitor Pattern
Collaborations
Double Dispatch• operation that gets executed depends on
– kind of request
– types of two receivers
– example: accept() is double dispatched operation. Its meaning depends on two types: Visitor’s and Element’s
Benefits and Drawbacks
Using Visitor at Oozinoz
• This initial work has to be done at design time
• The value of this approach is to allow new operations on machines without changing the machine hierarchy
The accept methods• The accept method in both the Machine class and the
MachineComponent class has identical code
• Even though the code looks identical, it cannot be pulled up to the parent class because of the “this”
Solution 29.1
• Here is the implementation of the MachineVisitor interface
The Oozinoz Factory in Dublin• The developers in Dublin, Ireland
have created an object model accessible through the static method dublin
• They display the components in a JTree
Finding a Machine within a Factory• We want to write a find method
to search for a particular machine in a factory yet not have to modify or even recompile the code for the factory composite
• Since the factory composite has now been set up to allow visitors this is possible
• We implement the MachineVisitor interface in a FindVisitor class
FindVisitor• The visit method does not
return a value
• So the FindVisitor records the status of the search in the found variable
• The tree traversal ends once the desired component is found
Solution 29.2
Double Dispatching
• Here we see the double dispatch typical of the visitor design pattern
• Accept passes in a handle to the caller
• The node in the hierarchy, where it is a MachineComposite or a Machine, calls visit to return a handle to itself
• This allows the visitor to access the node and perform whatever operation is needed
• We want to add a visitor that finds all leaf nodes in the tree
• We will collect the machines at the leaves in a set
Solution 29.3
Showing Our New Visitor at Work
Composites with Cycles• Our ProcessComponent
may have cycles
• We need to avoid infinite loops
• After disassembling an aeriel shell it is remade again
• This isn’t shown since the iterator doesn’t visit the same node twice
• We want some want to indicate a repeated step
Reworking the Code • Our desired printout is shown below
• We indicate the repeated step by printing … after the step is repeated
• We use a Hashset to store visited nodes
• If visited we print …
Visited Nodes
• We will indicate visiting a ProcessAlternation by printing a ? as a prefix
Demonstrating our New Output
• How can developers of the hierarchy, the ProcessComponent hierarchy in this case, help use detect cycles?
Solution 29.4
Use Visitor with Care
• Visitor is a “fragile” design pattern and must be used with care; if the base hierarchy changes frequently, this may not be a good choice
• Use Visitor if
Solution 29.5