Prototype Pattern
The Prototype Pattern is a creational design pattern that lets you copy existing objects without making your code dependent on their classes.
1. The Core Concept
Instead of building an object from scratch (which can be expensive if it involves database calls, network requests, or complex calculations), you take an existing object (the "prototype") and make a copy of it.
- Prototype Interface: Declares the cloning method.
- Concrete Prototype: Implements the cloning method.
- Client: Creates a new object by asking a prototype to clone itself.
2. Analogy: Cell Mitosis
In biology, a cell divides to create two identical daughter cells. The original cell acts as a prototype. This is much faster and more efficient than building a new cell from scratch with individual molecules.
3. Shallow vs. Deep Copy
A critical aspect of the Prototype pattern is how you handle the copy.
- Shallow Copy: Copies the top-level fields. If a field is a reference to another object, only the reference is copied, not the object itself. Both the original and the clone will point to the same nested object.
- Deep Copy: Copies everything. All nested objects are also cloned recursively. This creates a completely independent copy.
Choosing between them depends on your use case. Shallow copies are faster but can lead to unintended side effects if the shared nested objects are modified.
4. Example (TypeScript)
Let's model a registry of configurable shapes.
// The Prototype Interface
interface Shape {
clone(): Shape;
draw(): void;
}
// Concrete Prototype
class Circle implements Shape {
public radius: number;
public color: string;
constructor(source?: Circle) {
if (source) {
this.radius = source.radius;
this.color = source.color;
}
}
public clone(): Shape {
return new Circle(this);
}
public draw(): void {
console.log(`Drawing a ${this.color} circle with radius ${this.radius}`);
}
}
// Usage
const redCircle = new Circle();
redCircle.color = "red";
redCircle.radius = 10;
// Clone the prototype
const blueCircle = redCircle.clone() as Circle;
blueCircle.color = "blue"; // Modify the clone
redCircle.draw(); // Output: Drawing a red circle with radius 10
blueCircle.draw(); // Output: Drawing a blue circle with radius 10
5. Pros and Cons
| Pros | Cons |
|---|---|
| Performance: Avoids the cost of creating complex objects from scratch. | Complexity: Cloning objects with circular references can be very tricky. |
| Decoupling: The client code doesn't need to know the concrete classes of the objects it's cloning. | Implementation Overhead: You have to implement the cloning logic for every class in the hierarchy. |
| Convenience: Get a pre-configured object without writing initialization code. |
6. Use Cases
- Game Development: Cloning enemies with pre-set stats.
- UI Components: Creating copies of a pre-styled button.
- Configuration Objects: When you need a default configuration object that you can then customize.
programming/design-patterns programming/object-oriented-programming