Prototype Pattern
# Prototype Pattern
The Prototype Pattern is used to create duplicate objects while ensuring performance. This type of design pattern is a creational pattern and provides one of the best ways to create an object.
This pattern involves implementing a prototype interface which tells to create a clone of the current object. This pattern is used when creation of an object directly is costly. For example, an object is to be created after a costly database operation. We can cache the object, returns the clone on next request and update the database as and when needed thus reducing database calls.
## Summary
### Prototype Pattern
**Intent**: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
**Main Solution**: To dynamically add and remove prototypes at runtime.
### When to use
* When a system should be independent of how its products are created, composed, and represented.
* When the class to instantiate is specified at runtime, for example, by dynamic loading.
* To avoid building a class hierarchy of factories that parallels the class hierarchy of products.
* When instances of a class can have one of only a few different combinations of state. It may be more convenient to clone a prototype and change the state than to instantiate a new class.
### How to solve
Clone the existing object using a fast and efficient mechanism (e.g., binary cloning).
### Key Code
* Implement the clone operation:
* In Java, implement the `Cloneable` interface and override the `clone()` method.
* In .NET, use the `MemberwiseClone()` method of the `Object` class for a shallow copy, or use serialization for a deep copy.
* Isolate the client code from the concrete types of objects it needs to create, requiring the "volatile class" to have a stable interface.
### Application Examples
* Cell division.
* The `Object.clone()` method in Java.
### Advantages
* Performance improvement.
* Avoids the constraints of constructors.
### Disadvantages
* Implementing the clone method can be complex, especially if the class contains circular references or objects that do not support serialization.
* The `Cloneable` interface must be implemented.
### Use Cases
* Resource optimization.
* When class initialization consumes a lot of resources (e.g., data, hardware resources).
* Scenarios requiring high performance and security.
* When creating an object via `new` requires complex data preparation or access permissions.
* When an object needs multiple modifiers.
* When an object needs to be provided to other objects and might be modified by various callers.
* Often used with the Factory Method pattern, creating objects via `clone` and then providing them to callers via the factory method.
### Notes
Unlike directly instantiating a class to create new objects, the Prototype pattern generates new objects by copying existing objects. A shallow copy is achieved by implementing `Cloneable`, while a deep copy is achieved by implementing `Serializable` and reading the binary stream.
### Structure
The Prototype pattern includes the following main roles:
* **Prototype Interface**: Defines an interface for cloning itself, typically including a `clone()` method.
* **Concrete Prototype**: Implements the Prototype interface and is responsible for the actual cloning operation. This class needs to implement the `clone()` method, usually using shallow or deep copy to duplicate itself.
* **Client**: Uses a prototype instance to create new objects. The client calls the `clone()` method of the prototype object to create new objects, rather than using the constructor directly.
## Implementation
We are going to create an abstract class _Shape_ and concrete classes extending the _Shape_ class. Next step is to define the class _ShapeCache_, which stores shape objects in a _Hashtable_ and returns their clone when requested.
The _PrototypePatternDemo_ class will use _ShapeCache_ class to get a _Shape_ object.

### Step 1
Create an abstract class implementing the _Cloneable_ interface.
## Shape.java
```java
public abstract class Shape implements Cloneable{
private String id;
protected String type;
abstract void draw();
public String getType(){
return type;
}
public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
public Object clone(){
Object clone = null;
try{
clone = super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return clone;
}
}
### Step 2
Create concrete classes extending the above class.
## Rectangle.java
```java
public class Rectangle extends Shape{
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw(){
System.out.println("Inside Rectangle::draw() method.");
}
}
## Square.java
```java
public class Square extends Shape{
public Square(){
type = "Square";
}
@Override
public void draw(){
System.out.println("Inside Square::draw() method.");
}
}
## Circle.java
```java
public class Circle extends Shape{
public Circle(){
type = "Circle";
}
@Override
public void draw(){
System.out.println("Inside Circle::draw() method.");
}
}
### Step 3
Create a class to get concrete classes from database and store them in a _Hashtable_.
## ShapeCache.java
```java
import java.util.Hashtable;
public class ShapeCache{
private static HashtableshapeMap = new Hashtable();
public static Shape getShape(String shapeId){
Shape cachedShape = shapeMap.get(shapeId);
return(Shape)cachedShape.clone();
}
// For each shape run database query and create shape
// shapeMap.put(shapeKey, shape);
// For example, we are adding three shapes
public static void loadCache(){
Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(),circle);
Square square = new Square();
square.setId("2");
shapeMap.put(square.getId(),square);
Rectangle rectangle = new Rectangle();
rectangle.setId("3");
shapeMap.put(rectangle.getId(),rectangle);
}
}
### Step 4
_PrototypePatternDemo_ uses _ShapeCache_ class to get clones of shapes stored in the _Hashtable_.
## PrototypePatternDemo.java
```java
public class PrototypePatternDemo{
public static void main(String[]args){
ShapeCache.loadCache();
Shape clonedShape = (Shape)ShapeCache.getShape("1");
System.out.println("Shape : " + clonedShape.getType());
Shape clonedShape2 = (Shape)ShapeCache.getShape("2");
System.out.println("Shape : " + clonedShape2.getType());
Shape clonedShape3 = (Shape)ShapeCache.getShape("3");
System.out.println("Shape : " + clonedShape3.getType());
}
}
### Step 5
Verify the output.
Shape : Circle
Shape : Square
Shape : Rectangle
YouTip