tl  tr
  Home | Tutorials | Articles | Videos | Products | Tools | Search
Interviews | Open Source | Tag Cloud | Follow Us | Bookmark | Contact   
 Design Patterns > Java Design Patterns > Visitor

Visitor 

Visitor pattern comes under Behavioral design pattern. It allows us to define a new operation or algorithm without modifying the the object structure it operates.

Behaviour & Advantages

  • Represent an operation to be performed on the elements of an object structure.
  • Separates the algorithm from the object structure it operates.
  • Lets us define a new operation without changing the classes of the elements on which it operates.
  • Separates the related operations into a single class (Concrete Visitor) rather than polluting object structure.
Participants
  • Visitor
    Abstract interface for visiting the elements of object structure.
  • Concrete Visitor
    An implementation of Visitor interface.
  • Element
    Abstract interface to represent part or whole of object structure just like in composite pattern. Each element has to implement accept operation which takes a visitor as an argument.
  • Concrete Element
    An implementation of Element interface.
  • Object Structure
    It represents an element hierarchy and the root element to be visited.

This example shows a Shopping Cart where its items are visited by PrintShoppingCartVisitor to print the items and GenerateBillShoppingCartVisitor which generates and prints the bill.

Here IShoppingCartVisitor interface acts as Visitor. Classes PrintShoppingCartVisitor and GenerateBillShoppingCartVisitor acts as Concrete Visitors. Interface IShoppingCartElement and classes CartItem, Discount and VAT represents Element and Concrete Elements respectively. ShoppingCart represents the final Object Structure to be traversed.

Shopping cart element is shown below,

File Name  :  
com/bethecoder/tutorials/dp/visitor/IShoppingCartElement.java 
   
package com.bethecoder.tutorials.dp.visitor;

public interface IShoppingCartElement {
  public void accept(IShoppingCartVisitor shoppingCartVisitor);
}
   

Shopping cart visitor is shown below,

File Name  :  
com/bethecoder/tutorials/dp/visitor/IShoppingCartVisitor.java 
   
package com.bethecoder.tutorials.dp.visitor;

public interface IShoppingCartVisitor {
  public void visitShoppingCart(ShoppingCart shoppingCart);
  public void visitCartItem(CartItem cartItem);
  public void visitDiscount(Discount discount);
  public void visitVAT(VAT vat);
}
   

Print shopping cart concrete visitor.

File Name  :  
com/bethecoder/tutorials/dp/visitor/PrintShoppingCartVisitor.java 
   
package com.bethecoder.tutorials.dp.visitor;

public class PrintShoppingCartVisitor implements IShoppingCartVisitor {

  @Override
  public void visitCartItem(CartItem cartItem) {
    System.out.println(cartItem.getItemCount() " " 
        cartItem.getName().toUpperCase() "(S) each costing Rs." + cartItem.getPrice());
  }

  @Override
  public void visitDiscount(Discount discount) {
    System.out.println("Discount : " + discount.getDiscount() "%");
  }
  
  @Override
  public void visitVAT(VAT vat) {
    System.out.println("VAT : " + vat.getVat() "%");
  }

  @Override
  public void visitShoppingCart(ShoppingCart shoppingCart) {
    
    System.out.println("---- PrintShoppingCartVisitor ----");
    
    for (int i = ; i < shoppingCart.getCartItems().size() ; i ++) {
      shoppingCart.getCartItems().get(i).accept(this);
    }
    
  }

}
   

Generate bill concrete visitor.

File Name  :  
com/bethecoder/tutorials/dp/visitor/GenerateBillShoppingCartVisitor.java 
   
package com.bethecoder.tutorials.dp.visitor;

public class GenerateBillShoppingCartVisitor implements IShoppingCartVisitor {

  @Override
  public void visitCartItem(CartItem cartItem) {
    
    double itemCost = cartItem.getItemCount() * cartItem.getPrice();
    cartItem.getShoppingCart().setTotalBill(
        cartItem.getShoppingCart().getTotalBill() + itemCost);
    
    System.out.println(cartItem.getItemCount() " " 
        cartItem.getName().toUpperCase() 
        "(" + cartItem.getPrice() ") - Rs." + itemCost);
  }

  @Override
  public void visitDiscount(Discount discount) {
    System.out.println("\nTotal bill : " + discount.getShoppingCart().getTotalBill());
    discount.getShoppingCart().setTotalBill(
        discount.getShoppingCart().getTotalBill() (100-discount.getDiscount())/100);
    
    System.out.println("After Discount (" + discount.getDiscount() "%) : " 
        discount.getShoppingCart().getTotalBill());
  }

  @Override
  public void visitVAT(VAT vat) {
    System.out.println("\nTotal bill : " + vat.getShoppingCart().getTotalBill());
    
    vat.getShoppingCart().setTotalBill(
        vat.getShoppingCart().getTotalBill() (100+vat.getVat())/100);
    
    System.out.println("After VAT (" + vat.getVat() "%) : " 
        vat.getShoppingCart().getTotalBill());
  }
  
  @Override
  public void visitShoppingCart(ShoppingCart shoppingCart) {
    
    System.out.println("---- GenerateBillShoppingCartVisitor ----");
    
    for (int i = ; i < shoppingCart.getCartItems().size() ; i ++) {
      shoppingCart.getCartItems().get(i).accept(this);
    }
    
    System.out.println("\nAmount to pay : " + shoppingCart.getTotalBill());
  }

}
   

Shopping cart item concrete element.

File Name  :  
com/bethecoder/tutorials/dp/visitor/CartItem.java 
   
package com.bethecoder.tutorials.dp.visitor;

public class CartItem implements IShoppingCartElement {

  private String name;
  private int itemCount;
  private double price;
  private ShoppingCart shoppingCart;
  
  public CartItem(String name, int itemCount, double price) {
    super();
    this.name = name;
    this.itemCount = itemCount;
    this.price = price;
  }

  @Override
  public void accept(IShoppingCartVisitor shoppingCartVisitor) {
    shoppingCartVisitor.visitCartItem(this);
  }

  public double getPrice() {
    return price;
  }

  public void setPrice(double price) {
    this.price = price;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getItemCount() {
    return itemCount;
  }

  public void setItemCount(int itemCount) {
    this.itemCount = itemCount;
  }

  public ShoppingCart getShoppingCart() {
    return shoppingCart;
  }

  public void setShoppingCart(ShoppingCart shoppingCart) {
    this.shoppingCart = shoppingCart;
  }

}
   

Discount concrete element.

File Name  :  
com/bethecoder/tutorials/dp/visitor/Discount.java 
   
package com.bethecoder.tutorials.dp.visitor;

public class Discount implements IShoppingCartElement {

  private int discount;
  private ShoppingCart shoppingCart;
  
  public Discount(int discount) {
    super();
    this.discount = discount;
  }
  
  @Override
  public void accept(IShoppingCartVisitor shoppingCartVisitor) {
    shoppingCartVisitor.visitDiscount(this);
  }

  public int getDiscount() {
    return discount;
  }

  public void setDiscount(int discount) {
    this.discount = discount;
  }

  public ShoppingCart getShoppingCart() {
    return shoppingCart;
  }

  public void setShoppingCart(ShoppingCart shoppingCart) {
    this.shoppingCart = shoppingCart;
  }

}
   

VAT concrete element.

File Name  :  
com/bethecoder/tutorials/dp/visitor/VAT.java 
   
package com.bethecoder.tutorials.dp.visitor;

public class VAT implements IShoppingCartElement {

  private int vat;
  private ShoppingCart shoppingCart;
  
  public VAT(int vat) {
    super();
    this.vat = vat;
  }

  @Override
  public void accept(IShoppingCartVisitor shoppingCartVisitor) {
    shoppingCartVisitor.visitVAT(this);
  }

  public int getVat() {
    return vat;
  }

  public void setVat(int vat) {
    this.vat = vat;
  }

  public ShoppingCart getShoppingCart() {
    return shoppingCart;
  }

  public void setShoppingCart(ShoppingCart shoppingCart) {
    this.shoppingCart = shoppingCart;
  }
}
   

Shopping Cart object structure.

File Name  :  
com/bethecoder/tutorials/dp/visitor/ShoppingCart.java 
   
package com.bethecoder.tutorials.dp.visitor;

import java.util.ArrayList;
import java.util.List;

public class ShoppingCart implements IShoppingCartElement {

  private List<IShoppingCartElement> cartItems = 
          new ArrayList<IShoppingCartElement>();
  
  private double totalBill;
  
  public void addCartItem(CartItem shoppingCartElement) {
    shoppingCartElement.setShoppingCart(this);
    cartItems.add(shoppingCartElement);
  }
  
  public void addVAT() {
    VAT vat = new VAT(14);
    vat.setShoppingCart(this);
    cartItems.add(vat);
  }
  
  public void giveDiscount() {
    Discount discount = new Discount(10);
    discount.setShoppingCart(this);
    cartItems.add(discount);
  }

  @Override
  public void accept(IShoppingCartVisitor shoppingCartVisitor) {
    shoppingCartVisitor.visitShoppingCart(this);
  }

  public List<IShoppingCartElement> getCartItems() {
    return cartItems;
  }

  public void setCartItems(List<IShoppingCartElement> cartItems) {
    this.cartItems = cartItems;
  }

  public double getTotalBill() {
    return totalBill;
  }

  public void setTotalBill(double totalBill) {
    this.totalBill = totalBill;
  }
}
   

Visitor usage is shown below,

File Name  :  
com/bethecoder/tutorials/dp/visitor/Test.java 
   
package com.bethecoder.tutorials.dp.visitor;

public class Test {

  /**
   @param args
   */
  public static void main(String[] args) {

    ShoppingCart shoppingCart = new ShoppingCart();
    shoppingCart.addCartItem(new CartItem("Apple"412.50));
    shoppingCart.addCartItem(new CartItem("Mango"624.50));
    shoppingCart.addCartItem(new CartItem("Orange"86.50));
    shoppingCart.giveDiscount();
    shoppingCart.addVAT();
    
    shoppingCart.accept(new PrintShoppingCartVisitor());
    System.out.println();
    shoppingCart.accept(new GenerateBillShoppingCartVisitor());
  }

}
   

It gives the following output,
---- PrintShoppingCartVisitor ----
4 APPLE(S) each costing Rs.12.5
6 MANGO(S) each costing Rs.24.5
8 ORANGE(S) each costing Rs.6.5
Discount : 10%
VAT : 14%

---- GenerateBillShoppingCartVisitor ----
4 APPLE(12.5) - Rs.50.0
6 MANGO(24.5) - Rs.147.0
8 ORANGE(6.5) - Rs.52.0

Total bill : 249.0
After Discount (10%) : 224.1

Total bill : 224.1
After VAT (14%) : 255.474

Amount to pay : 255.474



 
  


  
bl  br