180 likes | 323 Views
Practical Session 11: The Visitor Pattern. Reminder: Polymorphic Variables. Reminder: Polymorphic Variables. Animal animal; animal = new Dog; animal.say(); \ “Woof” animal = new Cat; animal.say(); \ “Miau”. Animal * + say() *. Cat + say(). Dog + say(). System.out.println(“Woof”).
E N D
Reminder: Polymorphic Variables Animal animal; animal = new Dog; animal.say(); \\ “Woof” animal = new Cat; animal.say(); \\ “Miau” Animal * + say() * Cat + say() Dog + say() System.out.println(“Woof”) System.out.println(“Miau”)
What happens if a method accepts an argument? boolean b; Animal cat = new Cat(); Animal mouse = new Mouse(); b = cat.eats(mouse); //compilation error Animal * + say() * + eats(mouse: Mouse) : bool * + eats(cat: Cat): bool * Cat + say() + eats(mouse : Mouse) : bool + eats(cat : Cat) : bool Mouse + say() + eats(mouse : Mouse) : bool + eats(cat : Cat) : bool
No support forpolymorphism of arguments • Java (and many other languages) supports only polymorphism of the receiver (the variable on which the method is invoked). • Polymorphism of the receiver is performed using single dispatch. • Polymorphism of arguments is performed using multiple-level dispatch, which is resource consuming. Therefore, it is not supported. • Nevertheless, we can simulate it using the Visitor Pattern.
The visitor pattern (for methods with one argument) Define two interfaces: Visitor and Visited. • The Visitor interface contains a method for each possible argument type.
The visitor pattern (for methods with one argument) Define two interfaces: Visitor and Visited. • The Visitor interface contains a method for each possible argument type. Visitor +visit (cat : Cat) +visit (mouse : Mouse)
The visitor pattern (for methods with one argument) Define two interfaces: Visitor and Visited. • The Visitor interface contains a method for each possible argument type. • The Visited interface contains an accpet() method. Visitor +visit (cat : Cat) +visit (mouse : Mouse) Visited +accept(v : Visitor)
The visitor pattern (cont.) (for methods with one argument) • The reciever’s base class implements the visitor interface • The argument’s base class implements the visited interface
The visitor pattern (cont.) (for methods with one argument) • The reciever’s base class implements the visitor interface • The argument’s base class implements the visited interface Visitor +visit (cat : Cat) +visit (mouse : Mouse) Animal * +eats(animal: Animal)* +visit (cat : Cat)* +visit (mouse : Mouse)*
The visitor pattern (cont.) (for methods with one argument) • The reciever’s base class implements the visitor interface • The argument’s base class implements the visited interface Visitor +visit (cat : Cat) +visit (mouse : Mouse) Visited +accept (v : Visitor) Animal * +eats (animal: Animal)* +accept (v : Visitor)* +visit (cat : Cat)* +visit (mouse : Mouse)*
Implementation of Visited subclasses … public void accept(Animal animal){ animal.visit(this); } } Implementation of Visitor subclasses public class Cat extends Animal{ public void eats(Animal animal){ animal.accept(this); } public void visit(Cat cat){ s.o.p(“No”); } public void visit(Mouse mouse){ s.o.p(“Yes”); } …
Implementation of Visited subclasses … public void accept(Animal animal){ animal.visit(this); } } Implementation of Visitor subclasses public class Mouse extends Animal{ public void eats(Animal animal){ animal.accept(this); } public void visit(Cat cat){ s.o.p(“No”); } public void visit(Mouse mouse){ s.o.p(“No”); } …
Putting it all together Visitor +visit (cat : Cat) +visit (mouse : Mouse) Visited +accept (v : Visitor) Animal * +eats (animal: Animal) animal.accept(this) Cat +accept(animal: Animal) +visit (cat : Cat) +visit (mouse : Mouse) Mouse +accept(animal: Animal) +visit (cat : Cat) +visit (mouse : Mouse) animal.visit(this) animal.visit(this)
Different types of Visitor and Visited Employees and Reports example
Visitor visit(r : Regular) visit(m :Manager) visit(s :Specialist) Visited accept(v: Visitor) Employee accept(v: Visitor) Format print(e :Employee)+ e.accept(this) Regular accept(v: Visitor) + Manager accept(v: Visitor)+ Block visit(r: Regular)+ visit(m: Manager)+ visit(s: Specialist)+ Csv visit(r : Regular)+ visit(m :Manager)+ visit(s :Specialist)+ Specialist accept(v: Visitor)+ v.visit(this)
The Visitor Pattern Advantages • Simulating multiple-level dispatch. • Type-based treatment without instanceof. • Extending the functionality of a class hierarchy by an external class.
The Visitor Pattern Shortcomings • Tedious to code. • Adding a Visited class requires modifying existing Visitor classes. • Dispatching multiple arguments becomes inconvenient.