View
225
Download
1
Embed Size (px)
Citation preview
Design Patterns
Elements of Reusable Object-Oriented Software
by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (The Gang of Four).
Visitor Intent
• Given an existing structure such as a tree or graph whose nodes are objects from different classes
• Add new behavior to the system• Without adding new operations to the classes• By encapsulating the new behavior in visitor
objects• Which traverse the structure performing tasks
when they visit the nodes
Parse Tree Visitors
• A source programming file is parsed
• A parse tree is constructed
• Its nodes represents represent productions in the grammar (~100 different classes)
• We need to add compiler functionality:– Checking, code generation, optimization
• Without modifying the node classes
The Solution
• Add operations to the parse tree nodes
• To support a depth-first traversal of the tree
• By an abstract Visitor object.
• The Visitor has before and after methods for each kind of node.
• Class visitor{void before(expr e){}; void after(expr e){}
Double Dispatch
• The traversal code calls the Visitor’s before method when the visitor arrives at a node, its after method before it leaves the node.
• Concrete visitors do specific tasks such as checking and code generation
• The specific before and after methods called depend on the type of the concrete visitor and the type of the node. (double dispatch)
Visiting a Train
• <Train> -> <Engine> {<Car>}* abstract class Visitor{ public Visitor(){}
public void before(Train host){}
public void after(Train host){}
public void before(Engine host){}
public void after(Engine host){}
public void before(Car host){}
public void after(Car host){}
}
A visit method in the Train class
public void visit(Visitor v){ v.before(this);
if (engine!= null) engine.visit(v);
Enumeration enumCars = getCars().elements();
while(enumCars.hasMoreElements()){
Car it = (Car) enumCars.nextElement();
it.visit(v); }
v.after(this);
}