Chapter 8, Design Patterns Visitor Using UML, Patterns, and Java Object-Oriented Software Engineering
Pattern A Pattern Taxonomy Structural Pattern Behavioral Pattern Creational Pattern Composite Decorator Adapter Bridge Façade Proxy Iterator Visitor Command Observer Template Strategy Singleton Abstract Factory Builder Factory Prototype Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 2
the basics Intent: 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 aka: none! These slides were borrowed from lecture notes on Design Patterns by Brian Malloy at Clemson University Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 3
Motivation Consider a compiler that represents programs as 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 Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 4
Node class hierarchy Node typecheck() generatecode(); prettyprint(); VariableRefNode typecheck() generatecode(); prettyprint(); AssignmentNode typecheck() generatecode(); prettyprint(); Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 5
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! Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 6
Visitor allows us to separate Node classes from operations on Node classes allows each new operation to be added separately, without changing Node class! Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 7
Nodes accept visitors Node accept(nodevisitor) program v.visitassignment(this) VariableRefNode accept(nodevisitor) AssignmentNode accept(nodevisitor v) Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 8
Visitor for Nodes NodeVisitor visitassignment(node); visitvariableref(node); VariableRefNode visitassignment(node); visitvariableref(node); AssignmentNode visitassignment(node) visitvariableref(node) Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 9
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 Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 10
Structure of Visitor Pattern Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 11
Collaborations Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 12
Circularity inherent in Visitor pattern: Visitor needs elements & elements need Visitor emanates from double dispatch In Java, it s much easier, don t have to worry about forward references, or quick compiles C++ strives for efficiency, at a cost in programmer expertise Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 13
Single Dispatching Two criteria determine the operation: name of the request type of the receiver Example: calling node->generatecode() on an assignment Node will dynamically bind to the generatecode() function in AssignmentNode Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 14
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 Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 15
More implementation issues A visitor must visit each element of the structure Who is responsible for traversing the structure? object structure -- most often an iterator the visitor -- problem: you will likely dupe traversal code in each concrete visitor Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 16
Accumulating State Visitors can accumulate state as they traverse without a visitor, this state information might have to be passed during traversal Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 17
Consequences Easy to add new operations Visitor gathers related operations and separates unrelated operations Adding new ConcreteElement classes takes extra work -- need new abstract operation on Visitor Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 18