The Visitor Pattern for Polymorphic Variables
Learn about the Visitor Pattern, which allows simulating polymorphism of arguments in Java and other languages. Understand its advantages and shortcomings.
The Visitor Pattern for Polymorphic Variables
E N D
Presentation Transcript
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.