Understanding the Prototype Design Pattern in Java
The article explains the Prototype design pattern in Java, covering its definition, class diagram, implementation with Cloneable, shallow vs deep copying, advantages, use cases, Spring prototype scope, and provides complete code examples illustrating cloning of Sheep, Goat, and Lamb objects.
Problem
If you have an object and want to create an exact copy, you need to instantiate a new object of the same class and copy all member variables.
This straightforward approach can be inefficient for complex objects, may not handle private fields, and requires re‑initialisation each time.
Basic Introduction
Prototype pattern specifies creating objects by copying a prototype instance.
It is a creational design pattern that lets you clone existing objects without depending on their concrete classes.
The core mechanism is calling clone() on a prototype object.
Class Diagram
The diagram includes the following participants:
Prototype : an interface that declares the cloning method.
ConcretePrototype : classes that implement clone() and may handle special cloning logic.
Client : obtains a prototype instance and clones it to create new objects.
Example
We use a sheep‑herding story to demonstrate the pattern.
1. Prototype class (implements Cloneable )
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
class Sheep implements Cloneable {
private String name;
private Integer age;
private String color;
@Override
protected Sheep clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return sheep;
}
}2. Concrete prototypes
public class Goat extends Sheep {
public void graze() {
System.out.println("山羊去吃草");
}
} public class Lamb extends Sheep {
public void graze() {
System.out.println("羔羊去吃草");
}
}3. Client
public class Client {
static List
sheepList = new ArrayList<>();
public static void main(String[] args) {
Goat goat = new Goat();
goat.setName("山羊");
goat.setAge(3);
goat.setColor("灰色");
for (int i = 0; i < 5; i++) {
sheepList.add(goat.clone());
}
Lamb lamb = new Lamb();
lamb.setName("羔羊");
lamb.setAge(2);
lamb.setColor("白色");
for (int i = 0; i < 5; i++) {
sheepList.add(lamb.clone());
System.out.println(lamb.hashCode()+","+lamb.clone().hashCode());
}
for (Sheep sheep : sheepList) {
System.out.println(sheep.toString());
}
}
}The prototype pattern delegates cloning to the actual object, decoupling client code from concrete classes.
Advantages
Cloning via Object.clone() is a native method and often faster than repeatedly calling new , especially for large objects.
It simplifies object creation, making it as easy as copy‑paste in a document.
Useful when many similar objects need to be created inside loops, improving overall performance.
Applicable Scenarios
When object creation is expensive or complex.
When you need to copy objects without tying code to their concrete classes.
When subclass differences are only in initialization, allowing reduction of subclass count.
Prototype Pattern in Spring
Spring beans are singleton by default, but you can define a bean with scope="prototype" to obtain a new instance on each request.
<bean id="sheep" class="priv.starfish.prototype.Sheep" scope="prototype">
<property name="name" value="肖恩"/>
<property name="age" value="2"/>
<property name="color" value="白色"/>
</bean>Fetching the bean multiple times yields distinct objects.
Precautions
Cloning bypasses constructors; therefore, any initialization logic in constructors is not executed, which can conflict with patterns like Singleton.
Java's default clone() performs a shallow copy—reference‑type fields are shared.
Shallow vs Deep Copy
Shallow copy duplicates primitive fields but copies references for objects, leading to shared sub‑objects. Deep copy creates independent copies of referenced objects as well.
Shallow Copy Example
Sheep s = new Sheep();
s.setName("sss");
s.friend = new Sheep();
s.friend.setName("喜洋洋");
Sheep s1 = s.clone();
System.out.println(s == s1); // false
System.out.println(s.friend == s1.friend); // trueDeep Copy Approaches
Override clone() to recursively clone referenced objects.
Use object serialization to produce a deep copy.
When an object contains only primitive fields, the default clone behaves like a deep copy; otherwise, you must implement deep cloning manually.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.