Prototype Design Pattern
Also known as: Clone Pattern
Prototype is a Creational Design Pattern that allows you to create new objects by copying existing ones, without making your code dependent on their concrete classes.
Intent
Prototype lets you duplicate existing objects while hiding the complexity of object creation from the client code.
Instead of creating objects with new and configuring them repeatedly, you clone an already-configured object.
Problem
Imagine you are building a graphics editor.
You have shapes like:
- Circles
- Rectangles
- Text boxes
- Images
Each object contains:
- Position
- Color
- Border styles
- Shadow settings
- Metadata
- Event handlers
- Nested references
Now suppose the user clicks Duplicate Layer.
The naive approach would be:
Rectangle copy = new Rectangle();
copy.setWidth(original.getWidth());
copy.setHeight(original.getHeight());
copy.setColor(original.getColor());
copy.setBorder(original.getBorder());
copy.setShadow(original.getShadow());This creates several problems:
Tight Coupling
Your code depends on concrete classes.
Private Fields
Some fields may not be accessible externally.
Complex Initialization
Copying nested objects manually becomes painful.
Repeated Boilerplate
Every new class requires custom duplication logic.
As systems grow, cloning logic spreads everywhere.
Solution
The Prototype pattern delegates the cloning responsibility to the object itself.
Instead of asking:
“How do I create this object?”
You ask:
“Can you clone yourself?”
Each cloneable object exposes a common method:
clone()The object internally knows how to duplicate itself safely.
Real-World Analogy
Think about character presets in a video game.
You create:
- A warrior template
- A mage template
- An archer template
Each has predefined:
- Weapons
- Skills
- Armor
- Stats
Instead of building every character from scratch, the game clones a template and customizes it.
That template acts as a Prototype.
Structure
Basic Structure
The Prototype pattern usually contains:
1. Prototype Interface
Declares the cloning method.
interface Prototype {
Prototype clone();
}2. Concrete Prototype
Implements actual cloning logic.
class Circle implements Prototype {
int radius;
public Circle clone() {
Circle clone = new Circle();
clone.radius = this.radius;
return clone;
}
}3. Client
Uses prototypes without knowing their concrete classes.
Prototype shape = existingShape.clone();Example: Without Prototype
class UserProfile {
String name;
String theme;
List<String> permissions;
public UserProfile(
String name,
String theme,
List<String> permissions
) {
this.name = name;
this.theme = theme;
this.permissions = permissions;
}
}Usage:
UserProfile admin = new UserProfile(
"Admin",
"Dark",
List.of("READ", "WRITE", "DELETE")
);
UserProfile anotherAdmin = new UserProfile(
admin.name,
admin.theme,
admin.permissions
);This becomes messy very quickly.
Example: With Prototype
Step 1: Create Prototype Interface
interface Prototype<T> {
T clone();
}Step 2: Implement Prototype
class UserProfile implements Prototype<UserProfile> {
private String name;
private String theme;
private List<String> permissions;
public UserProfile(
String name,
String theme,
List<String> permissions
) {
this.name = name;
this.theme = theme;
this.permissions = permissions;
}
@Override
public UserProfile clone() {
return new UserProfile(
this.name,
this.theme,
new ArrayList<>(this.permissions)
);
}
@Override
public String toString() {
return name + " - " + theme + " - " + permissions;
}
}Step 3: Client Code
public class Main {
public static void main(String[] args) {
UserProfile admin = new UserProfile(
"Admin",
"Dark",
List.of("READ", "WRITE", "DELETE")
);
UserProfile clonedAdmin = admin.clone();
System.out.println(clonedAdmin);
}
}Shallow Copy vs Deep Copy
This is where most developers make mistakes.
Shallow Copy
Copies references.
clone.permissions = this.permissions;Both objects now share the same list.
Get Syed Hassan Hashmi’s stories in your inbox
Join Medium for free to get updates from this writer.
Changing one affects the other.
Deep Copy
Copies nested objects too.
new ArrayList<>(this.permissions)Each clone gets independent data.
Visualization
Prototype Registry
In large systems, creating prototypes repeatedly is inefficient.
A registry stores reusable prototypes.
Example
class ShapeRegistry {
private static final Map<String, Shape> shapes = new HashMap<>();
static {
shapes.put("circle", new Circle(10));
shapes.put("rectangle", new Rectangle(20, 30));
}
public static Shape getShape(String type) {
return shapes.get(type).clone();
}
}Usage:
Shape circle = ShapeRegistry.getShape("circle");This avoids expensive object creation.
When To Use Prototype
Use Prototype when:
Object Creation Is Expensive
- Database-heavy objects
- Config-heavy services
- Large graphs
You Need Runtime Object Duplication
Examples:
- Game entities
- UI components
- Diagram editors
You Want To Avoid Huge Constructors
Instead of:
new Car(...20 params...)Clone a configured object.
You Need Dynamic Object Creation
Especially when exact classes are unknown at runtime.
Real Industry Examples
Game Development
Games clone:
- Enemies
- Weapons
- NPCs
- Skill trees
instead of building them repeatedly.
UI Builders
Figma, Canva, Photoshop duplicate components using Prototype internally.
ORM Systems
Some ORMs duplicate query builders and configurations.
IDEs
Code templates and editor configurations often rely on cloning.
Pros and Cons
| Pros | Cons |
| ------------------------------------ | --------------------------------------- |
| Reduces repetitive initialization | Deep cloning can become complicated |
| Avoids tight coupling | Circular references are tricky |
| Faster object creation in some cases | Clone logic must stay updated |
| Simplifies dynamic object creation | Hidden shared references can cause bugs |Prototype vs Factory Method
| Prototype | Factory Method |
| -------------------------------- | ------------------------------- |
| Creates objects by cloning | Creates objects via inheritance |
| Focused on duplication | Focused on creation delegation |
| Faster for preconfigured objects | Better for controlled creation |
| Avoids subclass explosion | Can require many subclasses |Prototype vs Builder
| Prototype | Builder |
| ----------------------- | ------------------------- |
| Clones existing objects | Constructs step-by-step |
| Good for copying | Good for complex assembly |
| Fast duplication | Flexible customization |
| Uses existing state | Starts from scratch |Common Mistakes
1. Forgetting Deep Copy
This is the biggest issue.
Nested references remain shared accidentally.
2. Cloning Objects With External Resources
Examples:
- File handles
- DB connections
- Network sockets
These should not be blindly cloned.
3. Using Prototype Everywhere
Sometimes simple constructors are cleaner.
Prototype is useful only when duplication complexity becomes real.
Best Practices
Prefer Copy Constructors
In modern languages, copy constructors are often cleaner than raw clone() implementations.
Example:
UserProfile copied = new UserProfile(existingProfile);Keep Cloning Predictable
A clone should behave exactly like the original.
No side effects.
Clone Immutable Objects Carefully
Immutable objects often don’t need cloning at all.
Modern Perspective
In modern backend systems, Prototype is less visible directly, but its ideas appear everywhere:
- Object pools
- DTO duplication
- React state cloning
- Redux immutable updates
- Kubernetes template replication
- VM snapshots
- Container image layers
The pattern evolved beyond classic OOP textbooks.
Final Thoughts
Prototype is one of those patterns that seems simple initially but becomes incredibly valuable in large-scale systems.
Junior developers often see it as:
“Just copying objects.”
Senior engineers recognize it as:
- State replication
- Configuration templating
- Performance optimization
- Runtime flexibility
The real power of Prototype appears when object creation becomes expensive, repetitive, or dynamic.
Key Takeaways
- Prototype clones existing objects instead of creating from scratch.
- It reduces initialization complexity.
- Deep copy vs shallow copy is critical.
- Useful in games, editors, UI systems, and config-heavy applications.
- Great for reducing subclass explosion.
- Dangerous if cloning logic is poorly designed.







