Patrón Prototype: Clonación Eficiente de Objetos
design-patternscreationalprototype

Intención
El patrón Prototype permite crear nuevos objetos copiando una instancia existente (el prototipo), evitando el costo de crear objetos desde cero.
El Problema
Crear objetos complejos desde cero puede ser costoso:
// Crear un documento complejo es costoso
const doc1 = new Document();
doc1.loadTemplate('report');
doc1.applyStyles(defaultStyles);
doc1.initializePlugins(['charts', 'tables']);
// 500ms de inicialización...
// ¿Y si necesito 100 documentos similares?La Solución: Prototype
classDiagram
class Prototype {
<<interface>>
+clone(): Prototype
}
class ConcretePrototype {
-state: State
+clone(): ConcretePrototype
}
class Client {
-prototype: Prototype
+operation()
}
Prototype <|.. ConcretePrototype
Client --> PrototypeImplementación TypeScript
interface Cloneable<T> {
clone(): T;
}
interface DocumentConfig {
template: string;
styles: Record<string, string>;
plugins: string[];
metadata: {
author: string;
created: Date;
};
}
class Document implements Cloneable<Document> {
constructor(private config: DocumentConfig) {}
clone(): Document {
// Deep clone del config
return new Document({
...this.config,
styles: { ...this.config.styles },
plugins: [...this.config.plugins],
metadata: {
...this.config.metadata,
created: new Date(), // Nueva fecha para el clon
},
});
}
setAuthor(author: string): this {
this.config.metadata.author = author;
return this;
}
getConfig(): DocumentConfig {
return this.config;
}
}
// Registro de prototipos
class DocumentRegistry {
private prototypes = new Map<string, Document>();
register(name: string, prototype: Document): void {
this.prototypes.set(name, prototype);
}
create(name: string): Document {
const prototype = this.prototypes.get(name);
if (!prototype) throw new Error(`Prototype '${name}' not found`);
return prototype.clone();
}
}
// Uso
const registry = new DocumentRegistry();
// Registrar prototipos una vez (costoso)
registry.register('report', new Document({
template: 'report',
styles: { header: 'bold', body: 'normal' },
plugins: ['charts', 'tables'],
metadata: { author: '', created: new Date() },
}));
// Crear múltiples documentos (rápido)
const doc1 = registry.create('report').setAuthor('Alice');
const doc2 = registry.create('report').setAuthor('Bob');Shallow vs Deep Clone
// Shallow clone - comparte referencias
const shallowClone = { ...original };
// Deep clone - copia todo
const deepClone = structuredClone(original);
// Para objetos con métodos, implementar clone() manualmenteCuándo Usar
| Situación | Recomendación |
|---|---|
| Objetos costosos de crear | ✅ Recomendado |
| Templates o configuraciones base | ✅ Recomendado |
| Cachés de objetos | ✅ Recomendado |
| Objetos simples | ❌ new es suficiente |
Conclusión
Prototype es ideal cuando la creación desde cero es costosa y puedes reutilizar instancias existentes como punto de partida.