this is an assignement question from software engineering course and its a text book question..need help with the assignement as soon as possible!! please!and the textbook is fundamentals of software engineering second addition by carlo ghezzi and mehdi
Visitor Pattern
CSI 5390
Department of Computer Science and Engineering
Oakland University
Dae-Kyoo Kim
Intent
• To represent an operation to be performed
on the elements of an object structure
• How? – By letting you define a new operation without
changing the classes of the elements on
which it operates
Motivation
• Consider abstract syntax tree in a compiler
– Having many different kinds of nodes
• E.g., Assignment, Variable Reference, Arithmetic Expression
• Operations performed on the AST
– Checking for definition of variables
– Checking for variable assignment
– Type checking
– Code generation
– Pretty printing/formatting
Motivation (continued)
• These operations may need to treat each
type of node differently
• One way to do this is to define each
operation in the specific node class
Motivation (continued)
Motivation (continued)
• Problems with this approach:
– Adding new operations requires changes to
all of the node classes
– It can be confusing to have such a diverse set
of operations in each node class.
• E.g., mixing type-checking code with pretty-printing
code can be hard to understand and maintain
Motivation (continued)
• Solution
– Encapsulate a desired operation in a separate object,
called a visitor.
– The visitor object then traverses the elements of the
tree
– When an tree node "accepts" the visitor, it invokes a
method on the visitor that has the node type as an
argument.
– The visitor will then execute the operation for that
node (the operation that used to be in the node class)
Motivation (continued)
Solution for Abstract Syntax Tree
Applicability
• When an object structure contains many classes of objects, and operations should be performed on them
• When many distinct and unrelated operations need to be performed on objects in an object structure
• When the classes defining the object structure rarely change, but you often want to define new operations over the structure
Generic Solution: Structure
Generic Solution: Collaboration
Consequences
• Benefits
– Adding new operations is easy
– Related operations are localized and
unrelated ones are separated
– Accumulating state
• Liabilities
– Adding new ConcreteElement classes is hard
– Breaking encapsulation
Consequences
TypeEvalVisitor Sum.typeEval()
Difference.typeEval()
PrettyPrintVisitor Sum.prettyPrint()
Difference.prettyPrint()
TypeEvalVisitor Sum.typeEval()
Difference.typeEval()
Product.typeEval()
PrettyPrintVisitor Sum.prettyPrint()
Difference.prettyPrint()
Product.prettyPrint()
TypeEvalVisitor Sum.typeEval()
Difference.typeEval()
PrettyPrintVisitor Sum.prettyPrint()
Difference.prettyPrint()
ValueEvalVisitor Sum.prettyPrint()
Difference.prettyPrint()
Pro
Con
Single-Dispatch
• The actual method invoked depends on the
name of the request (method signature) and the
type of the receiver object
– E.g., calling foo() on a object of Type X, invokes the
foo() method of X
• The actual underlying type will be discovered
through polymorphism
• This is the standard technique used in
languages like Java and C++
Double-Dispatch
• The actual method invoked depends on
the name of the request and the types of
two receivers
– E.g., a VisitorA object calls accept(VisitorA) on
an ElementA object which calls visit(ElementA)
back to the VisitorA object
– This round trip ensures the right type of
Element and the correct visit() method of the
Visitor object
Sample Code in Java
public abstract class Component
{
protected String name;
public Component(String name) {this.name = name;}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public abstract double getPrice();
public abstract void accept(ComponentVisitor v);
}
Sample Code in Java (continued)
public class Widget extends Component
{
protected double price;
public Widget(String name, double price) {
super(name);
this.price = price;
}
public void setPrice(double price) { this.price = price; }
public double getPrice() { return price; }
public void accept (ComponentVisitor v) { v.visit(this); }
}
Sample Code in Java (continued)
public class WidgetAssembly extends Component
{
protected Vector components;
public WidgetAssembly (String name) {
super(name);
components = new Vector();
}
public void addComponent (Component c) {
components.addElement(c);
}
Sample Code in Java (continued)
public void removeComponent (Component c)
{
components.removeElement(c);
}
public double getPrice()
{
double totalPrice = 0.0;
Enumeration e = components.elements();
while (e.hasMoreElements())
{
totalPrice += ((Component) e.nextElement()).getPrice();
}
return totalPrice;
}
public void accept (ComponentVisitor v) { v.visit(this); }
Sample Code in Java (continued)
public abstract class ComponentVisitor
{
public abstract void visit(Widget w);
public abstract void visit(WidgetAssembly
wa);
}
Sample Code in Java (continued)
public class SimpleVisitor extends ComponentVisitor
{
public SimpleVisitor() {}
public void visit (Widget w)
{
System.out.println("Visiting a Widget");
}
public void visit (WidgetAssembly wa) {
System.out.println("Visiting a WidgetAssembly");
}
}
Sample Code in Java (continued)
public class PriceVisitor extends ComponentVisitor
{
private double maxPrice;
public PriceVisitor(double maxPrice)
{
this.maxPrice = maxPrice;
}
public void visit (Widget w)
{
double price = w.getPrice();
if (price > maxPrice)
System.out.println("Don't Buy! Widget price of " +
price + " exceeds maximum price (" + maxPrice + ").");
else
System.out.println("Buy! Widget price of " + price +
" is less than maximum price (" + maxPrice + ").");
}
Sample Code in Java (continued)
public void visit (WidgetAssembly wa)
{
double price = wa.getPrice();
if (price > maxPrice)
System.out.println("Don't Buy! WidgetAssembly price of " +
price + " exceeds maximum price (" + maxPrice + ").");
else
System.out.println("Buy! WidgetAssembly price of " +
price + " is less than maximum price (" + maxPrice + ").");
}
}
Sample Code in Java (continued)
• Visitor test program
public class VisitorTest
{
public static void main (String[] args) {
// Create some widgets.
Widget w1 = new Widget("Widget1", 10.00);
Widget w2 = new Widget("Widget2", 20.00);
Widget w3 = new Widget("Widget3", 30.00);
// Add then to a widget assembly.
WidgetAssembly wa = new WidgetAssembly("Chassis");
wa.addComponent(w1);
wa.addComponent(w2);
wa.addComponent(w3);
Object
structure
client
Sample Code in Java (continued)
// Visit some nodes with a SimpleVisitor.
SimpleVisitor sv = new SimpleVisitor();
w1.accept(sv);
w2.accept(sv);
w3.accept(sv);
wa.accept(sv);
// Visit some nodes with a PriceVisitor.
PriceVisitor pv = new PriceVisitor(25.00);
w1.accept(pv);
w2.accept(pv);
w3.accept(pv);
wa.accept(pv);
}
}
Sample Code in Java (continued)
• Execution
Visiting a Widget
Visiting a Widget
Visiting a Widget
Visiting a WidgetAssembly
Buy! Widget price of 10.0 is less than maximum price (25.0).
Buy! Widget price of 20.0 is less than maximum price (25.0).
Don't Buy! Widget price of 30.0 exceeds maximum price (25.0).
Don't Buy! WidgetAssembly price of 60.0 exceeds maximum price
(25.0).
Exercise
ExpressionNode
TypeCheck()
GenerateCode()
PrettyPrint()
Exercise
Expression
Node
Assignment
Node
VariableRef
Node1
VariableRef
Node2
Object Structure