Introduction
Have you ever found yourself writing the same object instantiation logic over and over again — just to get similar copies with minor differences?
The Prototype Design Pattern solves this by letting you clone existing objects instead of creating new ones from scratch. It's like photocopying a document instead of writing it all over again.
🧠 What is the Prototype Pattern?
The Prototype Pattern is a creational design pattern. It allows you to create new objects by copying an existing object (prototype), instead of building one using a constructor.
✅ Ideal when object creation is costly (due to time, complexity, or resource usage), or when you need many similar objects with small variations.
Real-Life Analogy
Imagine a resume builder website. You create your resume layout, style, and sections once, and then clone it to generate multiple versions tailored for different job applications.
You don’t start over each time — you clone the base resume (prototype), tweak the details, and go!
Structure of the pattern
interface Prototype {
Prototype clone();
}
class ConcretePrototype implements Prototype {
private String field;
public ConcretePrototype(String field) {
this.field = field;
}
@Override
public Prototype clone() {
return new ConcretePrototype(this.field);
}
}
Real-World Example: Document Template System
Imagine you're building a document editor application (like Google Docs or MS Word), where users can create documents based on predefined templates: resumes, invoices, reports, etc.
Instead of creating each document from scratch, the user selects a template, and your app clones it to create a new editable copy.
Step 1: Create a Prototype Interface
public interface DocumentPrototype {
DocumentPrototype clone();
}
Step 2: Implement the Concrete Class
public class Document implements DocumentPrototype {
private String type;
private String content;
private String header;
private String footer;
public Document(String type, String content, String header, String footer) {
this.type = type;
this.content = content;
this.header = header;
this.footer = footer;
}
@Override
public DocumentPrototype clone() {
return new Document(this.type, this.content, this.header, this.footer);
}
public void setContent(String content) {
this.content = content;
}
public void print() {
System.out.println("--- " + type + " Document ---");
System.out.println("Header: " + header);
System.out.println("Content: " + content);
System.out.println("Footer: " + footer);
}
}
Step 3: Clone and Customize Templates
public class DocumentManager {
public static void main(String[] args) {
// Original template
Document resumeTemplate = new Document("Resume", "Content Placeholder", "Resume Header", "Contact Info Footer");
// Clone template and customize
Document myResume = (Document) resumeTemplate.clone();
myResume.setContent("Priyank Sharma - Java Full Stack Developer");
Document anotherResume = (Document) resumeTemplate.clone();
anotherResume.setContent("Riya Mehta - UX Designer");
myResume.print();
anotherResume.print();
}
}
Output
--- Resume Document ---
Header: Resume Header
Content: Rupal Sharma - Java Full Stack Developer
Footer: Contact Info Footer
--- Resume Document ---
Header: Resume Header
Content: Riya Mehta - UX Designer
Footer: Contact Info Footer
✅ When to Use the Prototype Pattern
- Object creation is expensive (e.g., heavy DB calls, complex configuration)
- You need many similar objects
- You want to decouple the code from the actual class of the object
- You need runtime object cloning
🚫 When NOT to Use
- When objects are simple to construct
- If objects include non-cloneable resources (like sockets, file handles)
- You don’t want deep vs shallow copy confusion
🧩 Deep vs Shallow Copy
- Shallow Copy: Copies object references (shared data)
- Deep Copy: Recursively clones all objects (independent data)
- In Java, use
Cloneable
and overrideclone()
carefully to ensure deep copies when needed. You can also use copy constructors or serialization.
🧪 Bonus: Java's Built-in Cloneable
Java provides a Cloneable
interface and a clone()
method from Object. But it’s tricky:
class Product implements Cloneable {
String name;
public Product(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
However, Cloneable is controversial and error-prone. Most devs prefer manual cloning or copy constructors.
📦 Prototype in Popular Frameworks
- Spring Framework: Bean scope prototype is based on this pattern — a new instance is returned for each request.
- JavaScript: Object cloning using Object.create() or spread operators {...obj} is prototype-like.
- Game Engines: Unity, Unreal use prototypes for prefab systems.
📌 TL;DR
- Use Prototype when creating objects is expensive
- Clone a base object and customize as needed
- Be cautious with deep vs shallow copies
- Avoid overusing when simple constructors would do
🙌 Conclusion
The Prototype Pattern is a powerful but underrated tool in your design pattern arsenal. It’s all about efficiency and flexibility — especially when scaling object creation in complex systems.
Cloning isn’t just for sheep or sci-fi — it’s for smart devs too.
This is Part 4 of the Java Design Patterns Series.
If you find it insightful, please share your feedback. Also let me know if you have used prototype pattern in your projects.
Next Up: Builder Pattern – Construct objects piece by piece!
Top comments (0)