In this article, we will go through another pattern from behavioral category:Â Visitor Design Pattern.
The visitor design pattern is generally used when you have to do an operation on heterogeneous objects. The operation being performed is kept in different class and the objects of classes that need to be operated upon are passed to this method. This pattern can be used when you see:
- An object structure requires many unrelated operations
- There is the least possibility of change in any of the classes in the object structure.
- You need to work across several independent class hierarchies.
- New operations need to be added frequently.
xHere are ALL other Java Design Patterns, explained in detail with examplesx
Visitor Design Pattern by Example
To understand the pattern we will consider a real-world problem of Taxi Transport. In this, a taxi can transport persons, animals, and luggage. Based on type its fare may vary. We will apply Visitor Pattern to calculate total fare of the taxi.
Let us define a Transportable interface that will be implemented by each of the types that can be transported in a taxi.
public interface Transportable { public void accept(Visitor v); }
Now we will define Visitor interface
public interface Visitor { public void visit(Person p); public void visit(Animal a); public void visit(Luggage l); }
Note our Visitor interface has visit method for each of the type it is going to process.
The different types are implemented as
Person
public class Person implements Transportable { private double fare; private int numberOfPersons; public Person(double f, int n) { fare = f; numberOfPersons = n; } @Override public void accept(Visitor visitor) { visitor.visit(this); } //Getters //Setters }
Animal
public class Animal implements Transportable { private double fare; private int numberOfAnimals; public Animal(double f, int n) { fare = f; numberOfAnimals = n; } @Override public void accept(Visitor visitor) { visitor.visit(this); } //Getters //Setters }
Luggage
public class Luggage implements Transportable { private double fare; private double weight; public Luggage(double f, double w) { fare = f; weight = w; } @Override public void accept(Visitor visitor) { visitor.visit(this); } //Getters //Setters }
The concrete class which implements the Visitor interface does all the processing on each of the types
public class Taxi implements Visitor { private double totalFare; @Override public void visit(Person p) { totalFare = totalFare + (p.getFare() * p.getNumberOfPersons()); } @Override public void visit(Animal a) { totalFare = totalFare + (a.getFare() * a.getNumberOfAnimals()); } @Override public void visit(Luggage l) { totalFare = totalFare + (l.getFare() * l.getWeight()); } public double getTotalFare() { return totalFare; } }
Running the Example
public class TaxiBilling { public static void main(String args[]) { ListxTransportablex list = new ArrayListxTransportablex(); list.add(new Person(12.4f, 1)); list.add(new Animal(24.5f, 1)); list.add(new Luggage(10.9f, 5)); Taxi taxi = new Taxi(); for(Transportable t : list) { t.accept(taxi); } System.out.println(String.format("Total Fare : $%.2f", taxi.getTotalFare())); } }
See how our demo is iterating through all the transportable items and executing accept method.
Output
Total Fare : $91.40
Advantages
- Visitor pattern allows a new operation to be defined without any changes in the implementation of the class.
- If the logic of operation changes, then we need to make a change only in the visitor implementation, not in all the item classes.
Disadvantages
- If a new type is added, then a visitor interface and concrete class need to be modified.
- The superclass Visitor has to be aware of all types of nodes.
Conclusion
In this article, we understood Visitor Design Patter with the help of a simple example. The source code is available in our Github repository.
Download Codex
xHere are ALL other Java Design Patterns, explained in detail with examplesx