Prototype Pattern

What It Does
Why Use It?
- Avoid re-initializing complex objects.
- Create clones from templates (prototypes) instead of building from scratch.
- Keep code independent of object classes.
Real-World Analogy
TypeScript Example
Ts
// Prototype interface
interface Shape {
clone(): Shape;
}
// Base class with shared fields
abstract class BaseShape implements Shape {
constructor(
public x: number,
public y: number,
public color: string,
) {}
abstract clone(): Shape;
}
// Concrete prototype: Circle
class Circle extends BaseShape {
constructor(
x: number,
y: number,
color: string,
public radius: number,
) {
super(x, y, color);
}
clone(): Shape {
return new Circle(this.x, this.y, this.color, this.radius);
}
}
// Concrete prototype: Rectangle
class Rectangle extends BaseShape {
constructor(
x: number,
y: number,
color: string,
public width: number,
public height: number,
) {
super(x, y, color);
}
clone(): Shape {
return new Rectangle(this.x, this.y, this.color, this.width, this.height);
}
}
// Client code
const originalCircle = new Circle(10, 20, "blue", 30);
const clonedCircle = originalCircle.clone();
console.log("Original:", originalCircle);
console.log("Cloned:", clonedCircle);
console.log("Same object?", originalCircle === clonedCircle); // false (different instances)
When to Use Prototype
- You need exact copies of objects.
- You want to avoid subclassing just to change a few values.
- You don’t want to tightly depend on class names.
- You want to use pre-built templates (prototype registry).
Pros and Cons
- Copy objects without knowing their class.
- Reduces repeated setup/config code.
- An alternative to subclassing.
- Deep cloning (especially circular references) is tricky.
- Must implement clone() in every prototype class.