Prototype
Clone objects instead of creating new ones
Overview
The Prototype pattern creates new objects by cloning existing ones. Instead of creating objects from scratch, you copy an existing instance (prototype) and modify it as needed.
Useful when object creation is expensive, or when you want to create objects similar to existing ones.
Key Concepts
Clone existing objects instead of creating new
Shallow vs Deep copy
Prototype registry for managing cloneable objects
Avoids expensive initialization
Implements Cloneable interface in Java
Code Example
1// Prototype interface
2interface Prototype {
3 Prototype clone();
4}
5
6// Concrete prototype
7class GameCharacter implements Prototype {
8 private String name;
9 private int health;
10 private int level;
11 private List<String> inventory; // Reference type - needs deep copy
12 private Weapon weapon; // Reference type - needs deep copy
13
14 public GameCharacter(String name, int health, int level) {
15 this.name = name;
16 this.health = health;
17 this.level = level;
18 this.inventory = new ArrayList<>();
19 this.weapon = new Weapon("Sword", 10);
20 }
21
22 // Copy constructor for deep cloning
23 private GameCharacter(GameCharacter source) {
24 this.name = source.name;
25 this.health = source.health;
26 this.level = source.level;
27 // Deep copy of mutable objects
28 this.inventory = new ArrayList<>(source.inventory);
29 this.weapon = source.weapon.clone();
30 }
31
32 @Override
33 public GameCharacter clone() {
34 return new GameCharacter(this);
35 }
36
37 public void setName(String name) { this.name = name; }
38 public void addItem(String item) { inventory.add(item); }
39}
40
41class Weapon implements Prototype {
42 private String type;
43 private int damage;
44
45 public Weapon(String type, int damage) {
46 this.type = type;
47 this.damage = damage;
48 }
49
50 @Override
51 public Weapon clone() {
52 return new Weapon(this.type, this.damage);
53 }
54}
55
56// Prototype Registry
57class CharacterRegistry {
58 private Map<String, GameCharacter> prototypes = new HashMap<>();
59
60 public void register(String key, GameCharacter prototype) {
61 prototypes.put(key, prototype);
62 }
63
64 public GameCharacter create(String key) {
65 GameCharacter prototype = prototypes.get(key);
66 return prototype != null ? prototype.clone() : null;
67 }
68}
69
70// Usage
71public class Main {
72 public static void main(String[] args) {
73 // Create and configure prototype
74 GameCharacter warrior = new GameCharacter("Warrior", 100, 1);
75 warrior.addItem("Shield");
76 warrior.addItem("Helmet");
77
78 // Register prototype
79 CharacterRegistry registry = new CharacterRegistry();
80 registry.register("warrior", warrior);
81
82 // Create new characters by cloning
83 GameCharacter player1 = registry.create("warrior");
84 player1.setName("Player1");
85
86 GameCharacter player2 = registry.create("warrior");
87 player2.setName("Player2");
88
89 // Both have same stats and inventory, but are independent copies
90 }
91}GameCharacter is cloned using deep copy. New characters inherit the prototype's stats and inventory but are independent objects.
When to Use
When object creation is expensive
Creating objects with similar initial state
When you need to avoid subclasses for object creation
Dynamically loaded classes
Complex object initialization
Advantages
- ✓
Avoids expensive object initialization
- ✓
Simplifies creating similar objects
- ✓
Can add/remove objects at runtime
- ✓
Alternative to inheritance
Disadvantages
- ✗
Deep cloning can be complex
- ✗
Circular references require careful handling
- ✗
Clone method might be difficult for existing classes
💡 Interview Tips
Explain shallow vs deep copy
Discuss when cloning is better than creating
Know Java Cloneable interface limitations
Show prototype registry pattern
Compare with Factory (new vs clone)