Creational Design Pattern
![](https://codelido.com/assets/files/2022-12-18/1671386959-997657-single-ton-design-pattern-4.jpg)
Definition
The prototype pattern is used when the Object creation is costly and requires a lot of time and resources, and you have a similar Object already existing. So this pattern provides a mechanism to copy the original Object to a new Object and then modify it according to our needs. This pattern uses Java cloning to copy the Object. The prototype design pattern mandates that the Object which you are copying should provide the copying feature. It should not be done by any other class. However, whether to use the shallow or deep copy of the object properties depends on the requirements and is a design decision.
Characteristics
- Creates objects by cloning an existing prototype object, rather than creating new instances from scratch.
- Avoids the inherent cost of creating a new object in the standard way (e.g., using the new keyword) when it is prohibitively expensive for a given application.
- A prototype object is used as a blueprint for each object in the system, which allows for easy and quick customization of objects with minimal effort.
- Reduces the need for subclassing, since objects can be easily customized by cloning a prototype and altering a few properties.
- Encourages reuse of existing objects, rather than creating new ones from scratch.
UML Diagram
![](https://codelido.com/assets/files/2022-12-18/1671387044-839107-image.png)
Code
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;
}
}
public class Rectangle extends Shape {
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square extends Shape {
public Square(){
type = "Square";
}
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
public class Circle extends Shape {
public Circle(){
type = "Circle";
}
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
import java.util.Hashtable;
public class ShapeCache {
private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();
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);
}
}
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());
}
}
Output
Shape : Circle
Shape : Square
Shape : Rectangle
Advantages
- Complexity: Implementing a prototype pattern can be complex and requires a certain level of expertise. In addition, it may require extra time to develop the clone() method.
- Performance: The performance of the prototype pattern can be poor if the cloning process is not optimized.
- Limited Usability: The prototype pattern is only suitable for creating objects that are similar to existing ones. It’s not suitable for creating completely new objects.
- Security: Cloning an object can cause security issues if the object contains sensitive information that should not be accessible.
Disadvantages
The prototype pattern is based on cloning, which can be inefficient. Cloning can be quite expensive, depending on the complexity of the objects involved.
It can be difficult to maintain consistency across multiple copies of objects created by the prototype design pattern.
The prototype pattern can lead to a maintenance nightmare if there are a large number of prototypes and if these prototypes are not organized properly.
The prototype pattern can be difficult to test and debug, since it requires a lot of repetition of the same code.
The prototype design pattern can be difficult to understand, since the concept of cloning may not be familiar to all developers.