The Prototype Design Pattern: A Guide to Object Cloning in Java
Creational Design Patterns in Java (GOF)
Table of contents
• Introduction:
The Prototype design pattern is a creational design pattern that allows objects to be copied or cloned. It enables the creation of new objects by copying existing ones, thus avoiding the need for complex instantiation logic. This pattern promotes flexibility, efficiency, and maintainability by providing a mechanism for creating object instances based on prototypes. In this article, we will delve into the details of the Prototype design pattern and explore its implementation in Java.
• Overview:
The Prototype design pattern focuses on object cloning, providing a blueprint for creating new objects based on existing ones. By using the Prototype pattern, you can avoid the overhead of creating objects from scratch, especially when objects share similar attributes and behaviors. The pattern promotes code reusability and customization by allowing you to create new objects with predefined states.
• Example:
Let's consider an example to illustrate the Prototype pattern in action. Imagine you have a complex object hierarchy representing different types of shapes in a drawing application. Each shape has various attributes like color, size, and position. Instead of creating each shape from scratch and setting its attributes individually, the Prototype pattern allows you to clone an existing shape object and modify it as needed
. This approach saves time and simplifies the creation of new shapes with different configurations.
// Prototype interface
interface Shape extends Cloneable {
void draw();
Shape clone();
}
// Concrete prototype classes
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
@Override
public Shape clone() {
return new Rectangle();
}
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
@Override
public Shape clone() {
return new Circle();
}
}
// Prototype registry
class ShapeRegistry {
private static Map<String, Shape> shapeMap = new HashMap<>();
static {
shapeMap.put("rectangle", new Rectangle());
shapeMap.put("circle", new Circle());
}
public static Shape getShape(String type) {
Shape shape = null;
try {
shape = shapeMap.get(type).clone();
} catch (NullPointerException e) {
System.out.println("Shape not found: " + type);
}
return shape;
}
}
// Client code
public class Main {
public static void main(String[] args) {
Shape rectangle = ShapeRegistry.getShape("rectangle");
rectangle.draw();
Shape circle = ShapeRegistry.getShape("circle");
circle.draw();
}
}
In this example, we have an interface called Shape, which represents the prototype. The Rectangle and Circle classes implement the Shape interface and provide their own implementation of the draw() method and the clone() method
The ShapeRegistry class acts as a prototype registry, where predefined instances of shapes are stored. When a client requests a shape from the registry using the getShape() method, a clone of the corresponding shape is created and returned.
In the Main class, we demonstrate the usage of the Prototype pattern by obtaining instances of shapes from the ShapeRegistry and calling the draw() method on them.
• Conclusion:
By using the Prototype pattern, we can create new shape objects by cloning existing ones, without having to create them from scratch. This approach promotes code reusability, simplifies object creation, and allows for the customization of shapes based on specific requirements.