Prototype Design Pattern

Prototype design pattern is one of the creational design patterns.  This pattern clones the existing object instead of creating new one.  The cloning could be deep cloning or shallow cloning depending upon the context of the problem.

Prototype design pattern is useful when the creation of an object is expensive and consuming lot of time and resource.  In such cases, this pattern clones an already existing object and we could customize the cloned object as per our need.

Advantages

  1. When the creation of an object is expensive, time consuming and complex, this pattern takes care of creating such objects. 
  2. Client need not to know how to create this complex object.
  3. State of a cloned object could be modified if needed.

Example

Tea-Coffee spot is the place where tea and coffee are made with pre-defined notes.  When a client makes an order, the pre-defined note is cloned and given an order number.  The client can make changes to the cloned order that is add more sugar or less sugar or no sugar.  That is, the client has just cloned the tea/coffee and then customized it.

Example Diagram

Creating TeaCoffeeOrder Class

This class holds the responsibility of creating tea or coffee order based on the instructions provided by the client. This class implements cloneable interface and override the clone method to provide the clone object.

This class holds the core logic relevant to protype pattern.

package com.learningupskills.designpattern.prototype;

public class TeaCoffeeOrder implements Cloneable{
	
	private BevarageType type;	
	private SugarLevel sugarLevel = SugarLevel.NORMALSUGAR;
	private boolean isMilkBased = true;	
	private boolean isColdCofee;
	private int orderNumber;
	
	public TeaCoffeeOrder(String preparationNote, BevarageType type)
	{
		this.type = type;
	}

	
	public BevarageType getType() {
		return type;
	}

	public void setType(BevarageType type) {
		this.type = type;
	}

	public SugarLevel getSugarLevel() {
		return sugarLevel;
	}

	public void setSugarLevel(SugarLevel sugarLevel) {
		this.sugarLevel = sugarLevel;
	}

	public boolean isMilkBased() {
		return isMilkBased;
	}

	public void setMilkBased(boolean isMilkBased) {
		this.isMilkBased = isMilkBased;
	}

	public boolean isColdCofee() {
		return isColdCofee;
	}

	public void setColdCofee(boolean isColdCofee) {
		this.isColdCofee = isColdCofee;
	}
	
	public void printOrderDetails()
	{
		
		String isHotOrCold = this.isColdCofee?"Cold":"Hot";
		String isMilkOrWater = this.isMilkBased?"With":"Without";
		if(orderNumber ==0)
		{
			System.out.println("This is Original Object with below details:");
			System.out.println(isHotOrCold+type.toString()+" "+isMilkOrWater+" Milk and with "+sugarLevel.toString());


		}
		else
		{
			System.out.println("This is Prototyped/Cloned Object with order Number :"+orderNumber);
			System.out.println("You have ordered "+isHotOrCold+type.toString()+" "+isMilkOrWater+" Milk and with "+sugarLevel.toString());

		}
				
	}
	
	private void generateOrder()
	{
		 this.orderNumber =(int)(Math.random()*(10000-1000+1)+1000); 
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		this.generateOrder();
		return super.clone();
	}
}

Creating BevarageType enum

This enum represents different types of beverages such as coffee or tea

package com.learningupskills.designpattern.prototype;

public enum BevarageType {
	TEA, COFFEE;
}

Creating SugarLevel enum

This enum represents different amount of sugar can be added to beverages such as NOSUGAR, LESSSUGAR, NORMALSUGAR.

package com.learningupskills.designpattern.prototype;

public enum SugarLevel {
  NOSUGAR, LESSSUGAR, NORMALSUGAR, HIGHSUGAR;
}

Creating TeaShop Class

Teashop class is responsible for creating various tea and coffee combinations and stores as predefined notes.

Based on the order it fetches one of the predefined notes and makes the order by cloning.

Customization could be made such as less sugar, no sugar etc.

package com.learningupskills.designpattern.prototype;

import java.util.HashMap;
import java.util.Map;

public class TeaShop {
	//Notes for Coffee preparation
	private final static String  HOT_MILKCOFFEE_WITH_NORMALSUGAR="HOT_MILKCOFFEE_WITH_NORMALSUGAR";
	
	private final static String  HOT_BLACKCOFFEE_WITH_NORMALSUGAR="HOT_BLACKCOFFEE_WITH_NORMALSUGAR";
	
	private final static String  COLD_MILKCOFFEE_WITH_NORMALSUGAR="COLD_MILKCOFFEE_WITH_NORMALSUGAR";
	
	
	//Notes for Tea preparation
	
	private final static String  HOT_MILKTEA_WITH_NORMALSUGAR="HOT_MILKTEA_WITH_NORMALSUGAR";
	
	private final static String  HOT_BLACKTEA_WITH_NORMALSUGAR="HOT_BLACKTEA_WITH_NORMALSUGAR";	
	
	private final static String  ICE_TEA_WITH_NORMALSUGAR="ICE_TEA_WITH_NORMALSUGAR";

	
	
	
	private Map<String, TeaCoffeeOrder> similarOrders;
	private String teaShopName;
	
	public TeaShop(String teaShopName)
	{
		this.teaShopName = teaShopName;
		this.similarOrders =new HashMap<String, TeaCoffeeOrder>();
		this.prepopulatePreparationNote();
	}
	
	private void prepopulatePreparationNote()
	{
		//Pre populated coffee preparation note 
		orderTeaOrCoffe(TeaShop.HOT_MILKCOFFEE_WITH_NORMALSUGAR,true, true, SugarLevel.NORMALSUGAR, true);
		orderTeaOrCoffe(TeaShop.HOT_BLACKCOFFEE_WITH_NORMALSUGAR,true, true, SugarLevel.NORMALSUGAR, false);
		orderTeaOrCoffe(TeaShop.COLD_MILKCOFFEE_WITH_NORMALSUGAR,true, false, SugarLevel.NORMALSUGAR, true);
		
		
		//Pre populated tea preparation note 
		orderTeaOrCoffe(TeaShop.HOT_MILKTEA_WITH_NORMALSUGAR,false, true, SugarLevel.NORMALSUGAR, true);
		orderTeaOrCoffe(TeaShop.HOT_BLACKTEA_WITH_NORMALSUGAR,false, true, SugarLevel.NORMALSUGAR, false);
		orderTeaOrCoffe(TeaShop.ICE_TEA_WITH_NORMALSUGAR,false, false, SugarLevel.NORMALSUGAR, false);
		
	}
	
	
	public String getTeaShopName() {
		return teaShopName;
	}

	private TeaCoffeeOrder orderTeaOrCoffe(String preparationNote, boolean isCoffee, boolean isHot, SugarLevel level, boolean isMilkBased )
	{
		TeaCoffeeOrder order = new TeaCoffeeOrder(preparationNote, isCoffee?BevarageType.COFFEE:BevarageType.TEA);
		order.setColdCofee(isHot);
		order.setMilkBased(isMilkBased);
		order.setSugarLevel(level);
		similarOrders.put(preparationNote, order);
		return order;
	}

	
	public static void main(String[] args) throws CloneNotSupportedException {
		
		TeaShop shop = new TeaShop("SPSN Bhavan");
		System.out.println("Tea Shop Name :"+shop.teaShopName);		
		System.out.println("*********************************************************************************");

		//Original Note for ice tea with normal sugar
		TeaCoffeeOrder note1 = shop.similarOrders.get(ICE_TEA_WITH_NORMALSUGAR);
		note1.printOrderDetails();		

		System.out.println("---------------------------------------------------------------------------------");

		//Order(Cloned) for for ice tea with normal sugar
		TeaCoffeeOrder oreder1 = (TeaCoffeeOrder) note1.clone();
		
		//Customized to less sugar
		oreder1.setSugarLevel(SugarLevel.LESSSUGAR);
		oreder1.printOrderDetails();
		System.out.println("*********************************************************************************");
		
		//Original Note for hot black coffee with normal sugar
		TeaCoffeeOrder note2 = shop.similarOrders.get(HOT_BLACKCOFFEE_WITH_NORMALSUGAR);
		note2.printOrderDetails();	
		System.out.println("---------------------------------------------------------------------------------");

		//Order(Cloned) for hot black coffee with normal sugar
		TeaCoffeeOrder oreder2 = (TeaCoffeeOrder) note2.clone();
		//Customized to no sugar
		oreder2.setSugarLevel(SugarLevel.NOSUGAR);
		oreder2.printOrderDetails();
		System.out.println("*********************************************************************************");
		
		
		
		//Original Note for hot milk tea with normal sugar
		TeaCoffeeOrder note3 = shop.similarOrders.get(HOT_MILKTEA_WITH_NORMALSUGAR);
		note3.printOrderDetails();	
		System.out.println("---------------------------------------------------------------------------------");

		//Order(Cloned)  for hot milk tea with normal sugar
		TeaCoffeeOrder oreder3 =  (TeaCoffeeOrder) note3.clone();
		oreder3.printOrderDetails();
		System.out.println("*********************************************************************************");
		
	}
}

Result

Tea Shop Name :SPSN Bhavan

*********************************************************************

This is Original Object with below details:

HotTEA Without Milk and with NORMALSUGAR

———————————————————————–

This is Prototyped/Cloned Object with order Number :6239

You have ordered HotTEA Without Milk and with LESSSUGAR

********************************************************************

This is Original Object with below details:

ColdCOFFEE Without Milk and with NORMALSUGAR

———————————————————————–

This is Prototyped/Cloned Object with order Number :5889

You have ordered ColdCOFFEE Without Milk and with NOSUGAR

********************************************************************

This is Original Object with below details:

ColdTEA With Milk and with NORMALSUGAR

———————————————————————–

This is Prototyped/Cloned Object with order Number :1015

You have ordered ColdTEA With Milk and with NORMALSUGAR

********************************************************************

Scroll to top