What Problem It Solves
Creating a copy of an object is expensive (DB query, network call) or complex (deep graph of nested objects). Instead of re-creating from scratch, clone an existing instance and modify what's different.
Shallow vs Deep Copy
| Aspect | Shallow | Deep |
|---|---|---|
| Copies | References only | Creates new independent objects |
| Risk | Mutations affect both original and clone | Safe โ independent |
| Performance | Fast | Slower for deep graphs |
| Use when | Immutable children, or read-only shared state | Full isolation needed |
Where Prototype Appears in LLD
- Cache (#31): Clone a cached response instead of re-fetching
- Document Editor (not in problems, but common): Duplicate shapes/objects
- Config (#15): Clone default config, modify specific values
Implementation
// โโโ EXAMPLE 1 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// WHAT WE ARE IMPLEMENTING:
// A user authorization registry copying pre-configured permission templates
// (Admin, Guest).
//
// WHERE THE PATTERN FITS IN:
// UserPrototype is the Prototype interface declaring clone(). AdminPrototype
// and GuestPrototype are Concrete Prototypes cloned dynamically.
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// --- Prototype interface ---
interface ClonableDocument<T> {
T clone();
}
// --- Concrete prototype ---
class ReportDocument implements ClonableDocument<ReportDocument> {
private final String title;
private final String author;
private final java.util.List<String> sections;
private final java.util.Map<String, Object> metadata;
public ReportDocument(String title, String author) {
this.title = title;
this.author = author;
this.sections = new java.util.ArrayList<>();
this.metadata = new java.util.HashMap<>();
// Simulated expensive load
loadFromDatabase();
}
private void loadFromDatabase() {
System.out.println(" [DB] Loading report template...");
sections.add("Executive Summary");
sections.add("Findings");
sections.add("Recommendations");
metadata.put("template", "annual");
metadata.put("version", "v2");
}
// Private copy constructor โ the actual prototype mechanism
private ReportDocument(ReportDocument source) {
this.title = source.title;
this.author = source.author;
this.sections = new java.util.ArrayList<>(source.sections); // Deep copy
this.metadata = new java.util.HashMap<>(source.metadata);
}
public ReportDocument clone() {
System.out.println(" [Clone] Creating copy (no DB load)");
return new ReportDocument(this);
}
public void setTitle(String title) { this.title = title; }
@Override
public String toString() {
return "Report{title='" + title + "', author='" + author +
"', sections=" + sections + "}";
}
}
public class Main {
public static void main(String[] args) {
// Expensive creation โ happens once
ReportDocument template = new ReportDocument("Annual Report", "Default");
// Cheap clones โ customize each
ReportDocument report1 = template.clone();
report1.setTitle("2024 Annual Report");
ReportDocument report2 = template.clone();
report2.setTitle("2025 Annual Report");
System.out.println(report1);
System.out.println(report2);
}
}Review
Help Us Improve
How helpful was this walkthrough?
Click a star to rate. We actively use this feedback to refine and update our system design content.
Placeholder
Discussion
Share your thoughts, ask questions, or help others.
Loading comments...