Prototype Design Pattern in java
The Prototype Design Pattern is a creational
pattern that allows you to create new objects by copying existing ones,
rather than instantiating from scratch (i.e., using new).
Instead of building a new object, you clone a
pre-configured "prototype".
Intent
- Avoid
costly object creation (e.g. via constructors).
- Create
object copies quickly, especially when the structure is complex or
setup is time-consuming.
- Decouple
the code from specific classes (you work with prototypes, not concrete
constructors).
UML Structure
Components
Component |
Description |
Prototype |
Interface or abstract class declaring a clone() or copy()
method. |
ConcretePrototype |
Implements the clone() or copy() method to return a new
identical object. |
Client |
Requests clones instead of creating objects using new. |
Implementation in Java
There are two common ways to implement it:
a. Using Java’s built-in Cloneable interface:
- Implement
Cloneable.
- Override
clone() method from Object.
- Use
super.clone() to perform a shallow copy.
- For
deep cloning, clone nested mutable fields manually.
b. Using custom copy method or copy constructor:
- Define
a method like copy() or a copy constructor.
- Explicitly
return a new object with copied fields.
- Offers
more control, avoids exceptions and Cloneable quirks.
When to Use Prototype Pattern
Scenario |
Why Use Prototype? |
Object creation is expensive or slow |
Clone an existing setup |
Object has many configuration parameters |
Create and reuse prototype setup |
You want to avoid subclassing and prefer composition |
Clone instead of inheritance |
You need copies of objects with same values but separate
memory |
Deep clone via prototype |
You want to hide complexity of object creation from the
client |
Client only sees .clone() |
Advantages
✅ Speeds up object creation
✅
Simplifies object construction
✅
Avoids redundant initialization
✅
Can produce complex object structures easily
✅
Useful for creating object pools or registries
Disadvantages
❌ Can be error-prone if deep
cloning isn’t handled properly
❌
Using Cloneable has limitations (e.g., not supporting deep copy by default)
❌
Some developers consider clone() to be broken (as per Effective Java)
Example in Java API
Some Java classes that use the prototype pattern (or
something similar):
- java.lang.Object.clone()
- java.util.ArrayList.clone()
- java.util.HashMap.clone()
- java.awt.Graphics.clone()
Summary Table
Aspect |
Details |
Pattern Type |
Creational |
Key Method |
clone() or copy() |
Alternatives |
Builder Pattern, Factory Method |
Use in Java |
Common via Cloneable or manual copying |
Key Challenge |
Deep vs. shallow copying |
Example :-
package prototypedesignpattern;
public class Person implements
Cloneable {
private
String name;
private
int age;
public
Person(String name, int age) {
super();
this.name
= name;
this.age
= age;
}
public
String getName() {
return
name;
}
public
void setName(String name) {
this.name
= name;
}
public
int getAge() {
return
age;
}
public
void setAge(int age) {
this.age
= age;
}
@Override
public
String toString() {
return
"Person [name=" + name + ", age=" + age + "]";
}
protected
Object clone() throws CloneNotSupportedException {
return
super.clone();
}
}
package prototypedesignpattern;
public class ProtoTypePersonDemo {
public
static void main(String[] args) throws
CloneNotSupportedException {
Person
original = new Person("Govind", 34);
Person
copy = (Person) original.clone();
System.out.println("Original
:" + original);
System.out.println("Copy
:" + copy);
copy.setName("Ballabh");
copy.setAge(33);
System.out.println("After
modifying clone:");
System.out.println("Original:
" + original);
System.out.println("Clone:
" + copy);
}
}
o/p:
Original :Person [name=Govind, age=34]
Copy :Person [name=Govind, age=34]
After modifying clone:
Original: Person [name=Govind, age=34]
Clone: Person [name=Ballabh, age=33]
package prototypedesignpattern;
public class Employee {
private
String name;
private
int age;
public
String getName() {
return
name;
}
public
void setName(String name) {
this.name
= name;
}
public
int getAge() {
return
age;
}
public
void setAge(int age) {
this.age
= age;
}
public
Employee(String name, int age) {
super();
this.name
= name;
this.age
= age;
}
// Copy
constructor (used to create a new object from an existing one)
public
Employee(Employee e) {
super();
this.name
= e.name;
this.age
= e.age;
}
// Method to
manually clone/copy the object
public Employee
copy() {
return new
Employee (this);
}
@Override
public
String toString() {
return
"Employee [name=" + name + ", age=" + age + "]";
}
}
package prototypedesignpattern;
public class ProtoTypeEmployeeDemo {
public
static void main(String[] args) {
Employee
original = new Employee("Govind", 34);
Employee
copy = original.copy();
System.out.println("Original
:" + original);
System.out.println("Copy
:" + copy);
copy.setName("Ballabh");
copy.setAge(33);
System.out.println("After
modifying copy:");
System.out.println("Original:
" + original);
System.out.println("Copy:
" + copy);
}
}
o/p:
Original :Employee [name=Govind, age=34]
Copy :Employee [name=Govind, age=34]
After modifying copy:
Original: Employee [name=Govind, age=34]
Copy: Employee [name=Ballabh, age=33]
package prototypedesignpattern;
public class Student implements
Cloneable {
String name;
int age;
Address
address;
public
Student(String name, int age, Address address) {
super();
this.name
= name;
this.age
= age;
this.address
= address;
}
protected
Object clone() throws CloneNotSupportedException {
Student
student = (Student) super.clone();
student.address=
(Address)address.clone();// deep copy of address
return
student;
}
@Override
public
String toString() {
return
"Student [name=" + name + ", age=" + age + ",
address=" + address + "]";
}
}
package prototypedesignpattern;
public class PrototypeStudentDemo {
public
static void main(String[] args) throws
CloneNotSupportedException {
Address
addr = new Address("Delhi", "MG Road");
Student original = new
Student("Govind", 34, addr);
Student copy = (Student)
original.clone(); // Deep clone
System.out.println("Original:
" + original);
System.out.println("Copy : " + copy);
// Modify the clone
copy.name = "Amit";
copy.address.city = "Mumbai";
System.out.println("\nAfter
modifying the copy:");
System.out.println("Original:
" + original);
System.out.println("Copy : " + copy);
}
}
O/p :
Original: Student [name=Govind, age=34, address=Address [city=Delhi,
Street=MG Road]]
Copy : Student
[name=Govind, age=34, address=Address [city=Delhi, Street=MG Road]]
After modifying the copy:
Original: Student [name=Govind, age=34, address=Address
[city=Delhi, Street=MG Road]]
Copy : Student
[name=Amit, age=34, address=Address [city=Mumbai, Street=MG Road]]
No comments:
Post a Comment