Introducción al patrón Prototype
El patrón Prototype es un patrón creacional que permite crear nuevos objetos clonando instancias existentes (prototipos) en lugar de construirlos desde cero. Es especialmente útil cuando la creación del objeto es costosa, cuando queremos evitar cadenas de constructores complejas o cuando necesitamos copias configuradas en tiempo de ejecución. En esta guía verás ejemplos concretos en TypeScript y Java, pasos para aplicar el patrón y preguntas frecuentes con respuestas prácticas.
¿Cuándo usar Prototype?
- Cuando crear una instancia es costoso (operaciones I/O, cálculos, inicialización compleja).
 - Cuando se necesita duplicar objetos con configuraciones similares en tiempo de ejecución.
 - Cuando quieres separar la lógica de clonación (deep vs shallow) de la lógica de negocio.
 - Cuando buscas flexibilidad para registrar y clonar prototipos dinámicamente (registro/registry).
 
Implementación en TypeScript (ejemplo práctico)
En TypeScript es común implementar una interfaz con un método clone() que devuelva la copia. Punto importante: suele ser necesario decidir si la clonación será superficial (shallow) o profunda (deep). A continuación un ejemplo que muestra ambas variantes y un registry para reutilizar prototipos:
interface Prototype<T> {
  clone(deep?: boolean): T;
}
class Document implements Prototype<Document> {
  constructor(public title: string, public content: any) {}
  // clonación: por defecto shallow; si deep=true usamos JSON (simple deep clone)
  clone(deep = false): Document {
    if (!deep) {
      // shallow copy: new referencia para objeto raíz pero referencias internas iguales
      return new Document(this.title, this.content);
    }
    // deep copy (ejemplo simple): no válido para funciones o fechas complejas
    const copied = JSON.parse(JSON.stringify(this));
    return new Document(copied.title, copied.content);
  }
}
// Registry de prototipos
class PrototypeRegistry {
  private prototypes = new Map<string, Prototype<any>>();
  register(key: string, proto: Prototype<any>) {
    this.prototypes.set(key, proto);
  }
  clone<T>(key: string, deep = false): T | null {
    const p = this.prototypes.get(key) as Prototype<T> | undefined;
    return p ? p.clone(deep) as T : null;
  }
}
// Uso
const registry = new PrototypeRegistry();
const docPrototype = new Document('Plantilla', { sections: ['intro', 'body'] });
registry.register('doc:basic', docPrototype);
const copy1 = registry.clone<Document>('doc:basic'); // shallow
const copy2 = registry.clone<Document>('doc:basic', true); // deepNotas prácticas: usar JSON.parse/JSON.stringify para deep clone es rápido y sencillo, pero tiene limitaciones (no copia funciones, fechas, Map/Set ni referencias cíclicas). Para casos complejos usa librerías como lodash.clonedeep o una implementación personalizada.
Implementación en Java (ejemplo práctico)
En Java hay dos enfoques comunes: implementar Cloneable y sobrescribir clone() o usar constructores de copia (copy constructor). El enfoque del constructor de copia es más seguro y claro; el método clone() heredado de Object tiene peculiaridades y excepciones.
public class Document implements Cloneable {
    private String title;
    private List<String> sections;
    public Document(String title, List<String> sections){
        this.title = title;
        this.sections = sections;
    }
    // Copy constructor (forma recomendada)
    public Document(Document other){
        this.title = other.title;
        this.sections = new ArrayList<>(other.sections); // shallow copy de lista
    }
    // Método clone (puede lanzar CloneNotSupportedException)
    @Override
    public Document clone(){
        try{
            Document copy = (Document) super.clone();
            copy.sections = new ArrayList<>(this.sections); // clonar colección
            return copy;
        } catch(CloneNotSupportedException e){
            throw new AssertionError();
        }
    }
}
// Uso
Document proto = new Document("Plantilla", Arrays.asList("intro","body"));
Document copy = new Document(proto);Consejo: si tu objeto contiene referencias a objetos mutables, asegúrate de clonar esas referencias (deep copy) cuando sea necesario para evitar efectos colaterales.
Pasos prácticos para aplicar Prototype
- Identificar si la creación de objetos es costosa o si necesitas duplicados configurados.
 - Definir una interfaz/contrato que incluya un método clone() o usar copy constructors en Java.
 - Decidir política de clonación: shallow vs deep. Documentarlo claramente.
 - Implementar prototipos y, opcionalmente, un registry para gestionar instancias base reutilizables.
 - Escribir tests que verifiquen que las copias no comparten referencias mutables cuando no deben.
 
¿Prototype reemplaza a Factory o Builder?
No exactamente. Prototype se centra en clonar instancias existentes; Factory/Builder crean nuevas instancias a partir de parámetros. Usa Prototype cuando la clonación de una instancia existente es la forma más natural o eficiente. Usa Factory/Builder cuando la construcción paso a paso o parametrizada es prioritaria.
Preguntas frecuentes (Q&A)
¿Cuál es la diferencia entre shallow y deep clone?
Shallow clone copia las referencias de los campos (las colecciones y objetos internos siguen apuntando a los mismos objetos). Deep clone crea copias independientes de las estructuras internas. Elige shallow por rendimiento si los objetos internos son inmutables; elige deep cuando necesites independencia total.
¿Es seguro usar Object.clone() en Java?
El método clone() de Java funciona, pero tiene trampas: dependes de Cloneable, super.clone() y manejo de CloneNotSupportedException. Muchos prefieren constructores de copia o patrones como Builder para mayor claridad y control.
¿Cuándo NO usar Prototype?
Evítalo si la creación es barata o cuando la lógica de inicialización depende de parámetros externos que no vienen del prototipo base. Tampoco lo uses si la clonación profunda es tan compleja que es más simple construir desde cero.
| Patrón | Ventaja | Cuándo usar | 
|---|---|---|
| Prototype | Rápido para duplicar objetos configurados | Objetos costosos de crear o plantillas runtime | 
| Factory | Centraliza creación parametrizada | Cuando instancias varían según parámetros | 
| Builder | Construcción paso a paso y legible | Objetos complejos con muchas opciones | 
Conclusión: Prototype es una herramienta poderosa cuando se necesita clonar objetos con eficiencia y flexibilidad. Implementarlo bien implica decidir la estrategia de clonación, documentarla y probarla.