Showing posts with label E-commerce Example. Show all posts
Showing posts with label E-commerce Example. Show all posts

Saturday, 11 January 2014

Visitor Design pattern - Implementation [Products]

Master Practical Java Design Patterns!

Subscribe to Ram N Java for clean coding tutorials, behavioral design patterns, and real-world Java architecture implementations!

🔔 Subscribe to Ram N Java

The Problem: Adding Operations to Existing Classes

Imagine an e-commerce shopping cart containing various products—such as books, electronics, and fruits. Each product type has distinct pricing, shipping rules, and tax calculation formulas.

If you add new operations (like calculating discounted prices, export tariffs, or generating itemized receipts) directly into each product class, you violate the Open/Closed Principle. Every time business requirements introduce a new calculation or reporting feature, you are forced to modify and retest every product class.

The Solution: The Visitor Design Pattern

The Visitor Design Pattern separates an algorithm from the object structure on which it operates using a technique known as Double Dispatch:

  • Element Interface (Visitable): Declares an accept(Visitor visitor) method implemented by each product (e.g., Book, Fruit).
  • Visitor Interface: Defines dedicated visit methods for each concrete product type, such as visit(Book book) and visit(Fruit fruit).
  • Concrete Visitor: Encapsulates specific operational algorithms (e.g., ShoppingCartVisitor), computing costs and discounts based on the exact product type without polluting the product models.

Key Architectural Benefits

Applying the Visitor pattern to structured collections offers several advantages:

  • Open/Closed Principle: Add new operations (like tax auditing or loyalty points calculation) simply by introducing a new visitor class, leaving product classes untouched.
  • Single Responsibility Principle: Gathers related operations into a single class rather than scattering them across different element definitions.
  • Accumulated State: Visitors can maintain running states (such as running totals or item summaries) as they traverse a complex object structure.

Related Tutorials from Ram N Java



Click here to watch in Youtube : https://www.youtube.com/watch?v=tI3CRnDI3f0

Click the below Image to Enlarge
Visitor Design pattern - Implementation [Products]

Visitor Design pattern - Implementation [Products] - Class Diagram























Product.java

/*
 * Visitable Class
 */
public abstract class Product
{
protected int price;

public abstract void accept( ShoppingMallVisitor shoppingMallVisitor );

public int getPrice()
{
return price;
}
}

Book.java

public class Book extends Product
{

private String name;
private String isbnNumber;

public Book( String name, String isbnNumber, int price )
{
super();
this.name = name;
this.isbnNumber = isbnNumber;
this.price = price;
}

public String getName()
{
return name;
}

public String getIsbnNumber()
{
return isbnNumber;
}

@Override
public void accept( ShoppingMallVisitor shoppingMallVisitor )
{
shoppingMallVisitor.visit(this);
}

@Override
public String toString()
{
return "Book [name=" + name + ", isbnNumber=" + isbnNumber + ", price=" + price + "]";
}

}

DVD.java

public class DVD extends Product
{

private String name;

public DVD( String name, int price )
{
super();
this.name = name;
this.price = price;
}

public String getName()
{
return name;
}

@Override
public void accept( ShoppingMallVisitor shoppingMallVisitor )
{
shoppingMallVisitor.visit(this);
}

@Override
public String toString()
{
return "DVD [name=" + name + ", price=" + price + "]";
}

}

Shirt.java

public class Shirt extends Product
{

private String brandName;
private String size;

public Shirt( String brandName, String size, int price )
{
super();
this.brandName = brandName;
this.size = size;
this.price = price;
}

public String getBrandName()
{
return brandName;
}

public String getSize()
{
return size;
}

@Override
public void accept( ShoppingMallVisitor shoppingMallVisitor )
{
shoppingMallVisitor.visit(this);
}

@Override
public String toString()
{
return "Shirt [brandName=" + brandName + ", size=" + size + ", price=" + price + "]";
}

}

ShoppingMallVisitor.java

public interface ShoppingMallVisitor
{
public void visit(Product product);
}

Cashier.java

public class Cashier implements ShoppingMallVisitor
{

private String name;

private int    totalPrice = 0;

public int getTotalPrice()
{
return totalPrice;
}

public Cashier( String name )
{
super();
this.name = name;
}

public String getName()
{
return name;
}

@Override
public void visit( Product product )
{
totalPrice = totalPrice + product.getPrice();
}

}

ShoppingMallProducts.java

import java.util.ArrayList;
import java.util.LinkedHashMap;

public class ShoppingMallProducts
{

static LinkedHashMap<String, Product> productMap;

static
{
productMap = new LinkedHashMap<String, Product>();

Book weArebackBook = new Book("We are Back", "ISBN-999", 200);
Book jesusStoryBook = new Book("Jesus Story", "ISBN-1999", 500);
Book moralStoryBook = new Book("Moral Story", "ISBN-2999", 600);

DVD dieHard2Dvd = new DVD("Die Hard 2", 100);
DVD terminatorDvd = new DVD("The Terminator", 150);
DVD titanicDvd = new DVD("Titanic", 120);

Shirt zeroShirt = new Shirt("Zero", "42", 1500);
Shirt peterEnglandShirt = new Shirt("Peter England", "42", 2500);
Shirt johnPlayersShirt = new Shirt("John Players", "40", 2500);

productMap.put("weArebackBook", weArebackBook);
productMap.put("jesusStoryBook", jesusStoryBook);
productMap.put("moralStoryBook", moralStoryBook);
productMap.put("dieHard2Dvd", dieHard2Dvd);
productMap.put("terminatorDvd", terminatorDvd);
productMap.put("titanicDvd", titanicDvd);
productMap.put("zeroShirt", zeroShirt);
productMap.put("peterEnglandShirt", peterEnglandShirt);
productMap.put("johnPlayersShirt", johnPlayersShirt);

}

public int getTotalAmount( ArrayList<Product> purchasedProductList )
{
Cashier cashier = new Cashier("John");

System.out.println("Puschased Products details : \n");
for( Product product : purchasedProductList )
{
// Each product accepts the visitor
product.accept(cashier);
System.out.println(product+"\n");
}

return cashier.getTotalPrice();
}

}


Client.java

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Set;


public class Client
{

public static void main( String[] args )
{
LinkedHashMap<String, Product> productMap = ShoppingMallProducts.productMap;
Set<String> products=productMap.keySet();
System.out.println("Products Available \n");
for( String string : products )
                {
System.out.println(productMap.get(string));
                }
System.out.println(" \n############################################################# \n");
ArrayList<Product>    purchasedProductList = new ArrayList<Product>();
purchasedProductList.add(productMap.get("weArebackBook"));
purchasedProductList.add(productMap.get("jesusStoryBook"));
purchasedProductList.add(productMap.get("dieHard2Dvd"));
purchasedProductList.add(productMap.get("terminatorDvd"));
purchasedProductList.add(productMap.get("zeroShirt"));
purchasedProductList.add(productMap.get("peterEnglandShirt"));
ShoppingMallProducts shoppingMallProducts = new ShoppingMallProducts();
System.out.println("Total Amount : "+shoppingMallProducts.getTotalAmount(purchasedProductList) + "Rs");
}

}


Output

Products Available 

Book [name=We are Back, isbnNumber=ISBN-999, price=200]
Book [name=Jesus Story, isbnNumber=ISBN-1999, price=500]
Book [name=Moral Story, isbnNumber=ISBN-2999, price=600]
DVD [name=Die Hard 2, price=100]
DVD [name=The Terminator, price=150]
DVD [name=Titanic, price=120]
Shirt [brandName=Zero, size=42, price=1500]
Shirt [brandName=Peter England, size=42, price=2500]
Shirt [brandName=John Players, size=40, price=2500]
############################################################# 

Puschased Products details : 

Book [name=We are Back, isbnNumber=ISBN-999, price=200]

Book [name=Jesus Story, isbnNumber=ISBN-1999, price=500]

DVD [name=Die Hard 2, price=100]

DVD [name=The Terminator, price=150]

Shirt [brandName=Zero, size=42, price=1500]

Shirt [brandName=Peter England, size=42, price=2500]

Total Amount : 4950Rs


See also:

  • Visitor Design pattern - Introduction
  • Visitor Design pattern - Real time Example [Kids]
  • Visitor Design pattern - Real time Example [Products]
  • Visitor Design pattern - Class Diagram
  • Visitor Design pattern - Implementation [Kids]
  • Visitor Design pattern - KeyPoints
  • All Design Patterns Links
  • Tutorials