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

profileJenifer-bore_45
VisitorPattern.pdf

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