Low-level design2 min
Prototype Pattern
Type: Creational Pattern
Relevance: Medium. Useful in specific scenarios involving expensive initialization or complex states.
The Prototype pattern lets you copy (clone) existing objects without making your code dependent on their classes.
Real-Life Analogy
Think of cellular mitosis (cell division). When a cell needs to replicate, it doesn't build a new cell from scratch by collecting carbon and water molecules and assembling them. Instead, it creates an exact duplicate (a clone) of itself.
Alternatively, think of creating a presentation. Instead of creating a new PowerPoint from scratch, setting up all the fonts, master slides, and colors, you open an existing template (the prototype) and click "Duplicate".
The Problem
Imagine you have an object configured in a very specific, complex way. You want to create an exact copy of it.
- You can't just do
copy = new Object(), because you have to copy all private fields over (which might not be accessible from the outside). - Sometimes, you only know the interface of the object, not its concrete class, so you can't use
newanyway.
How to Implement Prototype
- Declare a
clone()method in an interface. - The concrete classes implement this method by creating a new instance of their own class and copying all field values from the current object into the new one.
Example in Code
interface Prototype {
clone(): Prototype;
}
class Monster implements Prototype {
public health: number;
public speed: number;
public weapons: string[];
constructor(health: number, speed: number, weapons: string[]) {
this.health = health;
this.speed = speed;
this.weapons = weapons;
}
// The Clone Method
public clone(): Monster {
// Note: If you have nested objects/arrays, you must ensure a DEEP COPY
// is performed so the clone doesn't share references with the original!
return new Monster(this.health, this.speed, [...this.weapons]);
}
}
// Setup a complex prototype once
const baseGoblin = new Monster(100, 15, ["Dagger", "Shield"]);
// When the player enters a room, just clone the base goblin!
// This is much faster than re-initializing complex logic.
const goblin1 = baseGoblin.clone();
const goblin2 = baseGoblin.clone();
// We can tweak the clone without affecting the prototype
goblin2.health = 120;
Class Diagram
Why is it Important?
- Performance: Cloning an object is often much faster and less resource-intensive than initializing a complex object from scratch (especially if initialization involves database calls or heavy computation).
- Flexibility: Allows you to copy objects without knowing their concrete classes, relying only on their shared interface.