Clonar objetos en lugar de construirlos desde cero es una de las estrategias más poderosas en el desarrollo de software orientado a objetos. El patrón Prototype permite crear copias exactas de instancias existentes, evitando la necesidad de definir múltiples subclases para cada variación de un producto. A continuación se explica paso a paso cómo se implementa en JavaScript, reutilizando código del patrón builder.
¿Cómo se estructura el patrón Prototype en JavaScript?
La implementación parte de dos elementos fundamentales que se reflejan en el diagrama del patrón [0:18]:
- Declarar una clase base o interfaz prototipo que contenga el método de clonación.
- Crear productos concretos que hereden de esa clase prototipo e implementen su propio método
clone.
El nombre de la clase base no tiene que llamarse literalmente "Prototype". Lo importante es que represente el producto que nos interesa clonar. En el ejemplo de la clase se reutiliza la clase Car del patrón builder, que ya cuenta con todos los métodos set necesarios para configurar un vehículo [0:38].
¿Qué hace el método clone dentro de la clase base?
El método clone se define en la clase Car para que todas las subclases lo hereden automáticamente. Cada subclase concreta decide cómo se realiza la clonación. Esto sigue el principio de que la implementación específica queda en manos de cada producto concreto [1:02].
¿Cómo implementan las subclases la clonación?
Tomemos como ejemplo MastodonCar, que hereda de Car [1:14]:
javascript
class MastodonCar extends Car {
constructor(carToClone) {
super();
// Se pasa toda la configuración del objeto original
}
clone() {
return new MastodonCar(this);
}
}
El método clone retorna una nueva instancia de MastodonCar, pero le pasa this como argumento. La palabra clave this hace referencia a la instancia que invoca el método, es decir, el objeto con toda su configuración actual [1:24]. Dentro del constructor, se utiliza la función super() para llamar al constructor de la superclase Car y transferir toda la información del vehículo original al nuevo objeto [1:40].
¿Cómo se verifica que la clonación funciona correctamente?
Primero se construye un vehículo Mastodon Sedan CVT de forma convencional. Después, se crea un clon llamando al método clone sobre esa instancia [2:08]:
javascript
const mastodonSedanCVT = buildMastodonSedanCVT();
const mastodonSedanCVTClone = mastodonSedanCVT.clone();
console.log(mastodonSedanCVTClone);
Al ejecutar el script, la consola muestra dos resultados [2:42]:
- El primer
console.log imprime: MastodonCar, edición CVT, modelo sedán, cuatro bolsas de aire, color rojo.
- El segundo
console.log muestra un objeto diferente pero con la misma configuración.
Esto confirma que se generó una copia independiente. Ya no es necesario crear subclases separadas para cada versión del vehículo (sedán, hatchback, CVT, signature). Se puede partir de una copia y modificarla según se necesite [2:58].
El mismo procedimiento se repite con la edición Signature, obteniendo el mismo resultado: dos objetos distintos con configuración idéntica [3:18].
¿Qué relación tiene el patrón Prototype con el propio JavaScript?
JavaScript ofrece herramientas nativas que permiten clonar objetos, pero la conexión va más allá de lo utilitario [3:48]. Antes de que existiera la sintaxis de clases en JavaScript, los prototipos eran la única forma de implementar programación orientada a objetos. La idea de tener un objeto base del cual otros heredan comportamiento es exactamente lo que propone el patrón Prototype [4:02].
Es muy probable que cuando se diseñó JavaScript, los fundamentos de este patrón de diseño ya estuvieran presentes como inspiración [4:18]. La herencia prototípica, concepto central del lenguaje, comparte raíces con el patrón creacional que permite generar nuevas instancias a partir de un modelo existente.
Si ya trabajaste con prototipos en JavaScript antes de la llegada de class, probablemente reconoces esta filosofía. ¿Consideras que el patrón de diseño influyó directamente en el lenguaje? Comparte tu opinión.