The Visitor Pattern in Java

Introduction to the Visitor Pattern

Design pattern in a simple meaning, is a way to design reusable object-oriented code. We can think of ways to design our classes, interfaces, enums and their members so that the code is reusable but flexible.

There are 23 most important design patterns, pioneered by the book Design Patterns: Elements of Reusable Object-Oriented Software, written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides or Gang of Four for short. We will cover these design pattern one by one.

By GoF definition, the Visitor pattern represents an operation to be performed on the elements of an object structure. The visitor lets us define a new operation without changing the classes of the elements on which it operates.

Implementation of Visitor Pattern in Java

Say we have a shopping cart which contains a lot of cart items, each item has some basic fields: name, unit price, quantity. Normally we would calculate each cart item by multiplying the unit price with the quantity. In the src folder we create the Item.java file:

public class Item{
  String name;
  int price;
  int qty;
  public Item(String name, int price, int qty){
    this.name = name;
    this.price = price;
    this.qty = qty;
  }
}

And in Test.java

import java.util.*;
public class Test {
  public static void main(String[] args){
    List<Item> carts = Arrays.asList(
        new Item("Lord of the Ring", 10, 3),
        new Item("Harry Porter", 9, 7)
    );
    carts.forEach(item->
      System.out.println(
        item.name + " - unit price: " +
        item.price + " - quantity: " +
        item.qty + " - total: " +
        item.qty * item.price
      )
    );
  }
}

Run Test.java

Lord of the Ring - unit price: 10 - quantity: 3 - total: 30
Harry Porter - unit price: 9 - quantity: 7 - total: 63

That’s good, but the Visitor pattern is even better, it can encapsulate the calculation of each item’s total to another class called the visitor class, so that when we want to change the formula, we just edit the visitor class.

Ok, first we create the Visitor interface:

public interface Visitor {
  int visit(Item item);
}

Next we create the CartItem interface that defines the action of the Item object:

public interface CartItem {
  int accept(Visitor visitor);
}

Now we will change the Item class like this:

public class Item implements CartItem{
  String name;
  int price;
  int qty;
  public Item(String name, int price, int qty){
    this.name = name;
    this.price = price;
    this.qty = qty;
  }
  public int accept(Visitor visitor) {
    return visitor.visit(this);
  }
}

OK, normally this should be an abstract class for all the element ojects of the shopping cart, but for simplicity we use this concrete class. Next we create the real Visitor, in this class we will define the formula to calculate the total sum of each cart element. Here is the CartVisitor.java:

public class CartVisitor implements Visitor{
  public int visit(Item item) {
    return item.price * item.qty;
  }
}

Yep, still the same formula as the previous version (ok, for simplicity). And finally in Test.java:

import java.util.*;
public class Test {
  public static void main(String[] args){
    List<Item> carts = Arrays.asList(
        new Item("Lord of the Ring", 10, 3),
        new Item("Harry Porter", 9, 7)
    );
    carts.forEach(item->
      System.out.println(
        item.name + " - unit price: " +
        item.price + " - quantity: " +
        item.qty + " - total: " +
        item.accept(new CartVisitor())
      )
    );
  }
}

Run the code and we have the output:

Lord of the Ring – unit price: 10 – quantity: 3 – total: 30
Harry Porter – unit price: 9 – quantity: 7 – total: 63
[/txt]

Later, we can make change to the CartVisitor class and define the result of each cart item. And the other code will still work.

Leave a Reply