Prototype pattern refers to creation of new objects through cloning of the existing objects. This type of design pattern comes under creational pattern as this pattern provides one of the best way to create an object. By creating a prototype, new objects are created by copying this prototype. This pattern is used when creation of object directly is costly.
For example, being the database operation costly, we create an object in first request and in subsequent requests we can cache the object, returns its clone as and when needed thus reducing the database calls.
Class Diagram
When to use
We want to add and remove objects at runtime.
We want to cache objects for better performance.
We can configure an application with classes dynamically.
We want to keep the number of classes in a system to be minimum.
Benefits
Speeds up instantiation of large, dynamically loaded classes.
Reduced sub-classing.
Disadvantages
Each subclass of Prototype must implement the Clone operation. Could be difficult with existing classes with internal objects with circular references or which does not support copying.
Implementation
Let’s create an abstract class Burger and concrete classes extending the Burger class. A class PrototypeCache is defined as a next step which stores Burger objects in a Hashtable and returns their clone when requested. The demo class, PrototypDemo, will use PrototypeCache class to get a Burger object.
package com.roytuts.designpattern.prototype; public abstract class Burger implements Cloneable { private String name; private String description; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public Object clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return object; } public abstract float getPrice(); }
package com.roytuts.designpattern.prototype; public class VegBurger extends Burger { @Override public float getPrice() { return 50f; } }
package com.roytuts.designpattern.prototype; public class ChickenBurger extends Burger { @Override public float getPrice() { return 110f; } }
package com.roytuts.designpattern.prototype; import java.util.Hashtable; public class PrototypeCache { Hashtable<String, Burger> burgerTable = new Hashtable<String, Burger>(); public Burger getBurger(String type) { Burger cachedBurger = burgerTable.get(type); return (Burger) cachedBurger.clone(); } public void loadCache() { VegBurger vegBurger = new VegBurger(); vegBurger.setName("Veg Tikka"); vegBurger.setDescription("Contains different vegetables"); burgerTable.put("veg", vegBurger); ChickenBurger chickenBurger = new ChickenBurger(); chickenBurger.setName("Chicken Maharaja"); chickenBurger.setDescription("Contains different vegetables and cheese and chicken"); burgerTable.put("chicken", chickenBurger); } }
package com.roytuts.designpattern.prototype; public class PrototypeDemo { /** * @param args */ public static void main(String[] args) { PrototypeCache prototypeCache = new PrototypeCache(); prototypeCache.loadCache(); VegBurger vegBurger = (VegBurger) prototypeCache.getBurger("veg"); System.out.println("Name: " + vegBurger.getName()); System.out.println("Price: Rs. " + vegBurger.getPrice() + "/-"); System.out.println("Description: " + vegBurger.getDescription()); System.out.println(); ChickenBurger chickenBurger = (ChickenBurger) prototypeCache.getBurger("chicken"); System.out.println("Name: " + chickenBurger.getName()); System.out.println("Price: Rs. " + chickenBurger.getPrice() + "/-"); System.out.println("Description: " + chickenBurger.getDescription()); } }
Output
Name: Veg Tikka Price: Rs. 50.0/- Description: Contains different vegetables Name: Chicken Maharaja Price: Rs. 110.0/- Description: Contains different vegetables and cheese and chicken
That’s all. Thank you for your reading.