Patrones de diseño de JavaScript Parte 1: El patrón de fábrica

Foto de Patrick Hendry en Unsplash

Últimamente, a medida que los proyectos en los que he tenido la oportunidad de trabajar han crecido en escala, me he tomado el tiempo para profundizar en los patrones de diseño para escribir código Javascript más escalable y fácil de mantener. Los patrones de diseño son una excelente manera de aplicar soluciones probadas en tiempo y batalla a problemas comunes para que podamos resolverlos de manera más rápida y eficiente.

La mayoría de los patrones de diseño que cubriremos se basan en la Programación Orientada a Objetos y, como tal, solo tiene sentido que comencemos por observar un patrón creacional llamado así porque el patrón nos proporciona una interfaz clara para crear objetos mientras abstraemos la variada complejidad o lógica involucrada en su creación. Este patrón se llama Patrón de Fábrica y nos permite crear fácilmente objetos en JavaScript.

Viniendo de otros OOP, lenguajes basados ​​en clases, uno podría sentirse tentado a pensar que lo que haremos en las líneas de código a continuación es crear clases e instancias, pero en realidad esto es solo azúcar sintáctico hecho para parecerse a la sintaxis de una clase lenguaje basado.

Lo que realmente estamos haciendo es aprovechar la herencia prototípica de JavaScript y OLOO - Objetos que enlazan con otros objetos para crear objetos con un prototipo compartido. El prototipo en sí es solo un objeto JavaScript simple y no una clase en el verdadero sentido de la palabra. Una gran explicación de la herencia en Javascript y sus diferencias con la herencia clásica se puede encontrar en el artículo de Eric Elliot aquí.

Vamos a sumergirnos en un código.

Todos los ejemplos de esta serie estarán disponibles en Github aquí e incluyen instrucciones sobre cómo ejecutar el código.

Para ejecutar el código en este artículo, necesitará tener Nodo instalado en su máquina. Siga estas instrucciones si aún no lo tiene. Si sigue junto con el repositorio, encontrará instrucciones para ejecutar el código en el archivo Léame.

Lo primero es lo primero, creemos una carpeta. Podemos llamarlo javascript-design-patterns en esta carpeta, crearemos una carpeta de fábrica.

El patrón de fábrica en acción

El patrón de fábrica envuelve un constructor para diferentes tipos de objetos y devuelve instancias de los objetos a través de una API simple. Facilita la creación de diferentes objetos al exponer una API simple que devuelve el tipo de objeto especificado.

Comencemos creando nuestros constructores. Estas funciones serán responsables de devolver nuevos objetos de un tipo específico cuando se invoquen.

En la carpeta de fábrica, creemos un archivo laptop.js.

const Laptop = function ({ram, hdd, name}) {
  this.ram = ram || 0;
  this.hdd = hdd || 0;
  this.name = name || "";
};
module.exports = Laptop;

En este archivo, creamos una función de construcción de Laptop. Acepta un objeto como parámetro con atributos para crear instancias del objeto con varias especificaciones que deseamos capturar, en este caso, el tamaño de RAM, el tamaño del disco duro y el nombre del dispositivo.

Después de eso, exportamos la función de construcción Laptop desde el módulo.

Vamos a crear otro archivo llamado tablet.js

Haremos lo mismo pero con especificaciones más relevantes para una tableta.

const Tablet = function ({ram, hdd, name, network}) {
    this.ram = ram || 0;
    this.hdd = hdd || 0;
    this.network = red || 0;
    this.name = name || "";
};
module.exports = Tablet;

Ahora que tenemos nuestros constructores, creemos la función de fábrica que expondrá la API para crear nuevas instancias de estos elementos. Agregue un nuevo archivo llamado gadgetFactory.js

const Laptop = require ("./ laptop");
const Tablet = require ("./ tablet");
const gadget = {Laptop, Tablet};
module.exports = {
    createGadget (tipo, atributos) {
        const GadgetType = gadget [tipo];
        devolver nuevo GadgetType (atributos);
    }
};

Aquí, comenzamos importando los constructores para crear objetos Laptop y Tablet. Luego creamos un objeto gadget usando los nombres de constructor como claves. Esto nos permite acceder al tipo de constructor que queremos usar gadget [tipo], donde en este ejemplo, el tipo será "Laptop" o "Tablet". Finalmente, exportamos un objeto desde este módulo con un método createGadget. Este método acepta un tipo de gadget como primer parámetro y llama al tipo de constructor especificado mientras le pasa los atributos.

Debe tener en cuenta que cuando llamamos a una función con la nueva palabra clave en Javascript, obtenemos un objeto vacío con este conjunto de enlaces al de la función de ejecución. Esta llamada única también creará una relación prototípica entre la función del constructor y cualquier objeto nuevo que creamos de esta manera. Lo veremos en detalle en los otros patrones de diseño que cubriremos.

También cabe destacar que la primera letra mayúscula es solo una convención y no un requisito. No hace nada especial y podríamos haber nombrado las funciones con camelCase como lo hacemos habitualmente con otras variables y nombres de funciones en JavaScript.

En este punto, ahora podemos crear el archivo que utilizará (o consumirá) nuestra API de patrón de fábrica.

Cree un archivo index.js y agregue el siguiente código.

const gadgetFactory = require ("./ gadgetFactory");
const myLaptop = gadgetFactory.createGadget ("Laptop", {
    ram: 8,
    ssd: 256,
    nombre: "Bab's MacBook Pro"
});
const myTablet = gadgetFactory.createGadget ("Tableta", {
    ram: 4,
    disco duro: 128,
    nombre: "iPad de Bab",
    red: '4G'
});
console.log (myLaptop);
console.log (myTablet);

Lo primero que puede notar es que en este archivo, no requerimos los constructores para computadoras portátiles y tabletas directamente. Todo lo que necesitamos es el módulo gadgetFactory (con su método createGadget). Con este método, creamos dos instancias de una computadora portátil y una tableta, respectivamente, y las desconectamos de la consola.

Ahora en su terminal navegue a la carpeta javascript-design-patterns y escriba:

$ nodo ./factory/index.js

Debería ver lo siguiente registrado en la consola:

Laptop {ram: 8, ssd: 256, nombre: 'Bab \' s MacBook Pro '}
Tableta {ram: 4, disco duro: 128, red: '4G', nombre: 'Bab \' s iPad '}

Como puede ver, creamos un tipo de objeto Laptop y un tipo Tablet, cada uno con sus propias especificaciones. Con este patrón, puede crear tantos objetos de gadget como necesite, cada uno con sus propias especificaciones.

Y eso es todo por el patrón de fábrica. Por supuesto, esta es una implementación bastante simplista, y en cualquier otra cosa que no sea una aplicación trivial definitivamente querrás incluir una lógica más estricta, por ejemplo, alrededor de tus constructores.

En este ejemplo, utilizamos las funciones de constructor de Javascript, pero este patrón también se puede implementar mediante prototipos. Exploraremos esto en un artículo posterior cuando refactoricemos nuestro código para hacerlo más eficiente.

A continuación en la serie, cubriremos el popular patrón de editor / suscriptor (o PubSub para abreviar). Para mantenerte informado, asegúrate de darme un seguimiento y, si encuentras útil este artículo, deja un pulgar hacia arriba (o 5 5). ¡Como siempre, me encantaría saber tu opinión en los comentarios a continuación!

Actualización: Aquí puede encontrar la Parte 2 de la serie que cubre el patrón Editor / Suscriptor.

Babs es un desarrollador de JavaScript que escribe principalmente React / React Native & NodeJS (con una buena dosis de GraphQL) durante el día y todo lo demás JavaScript bajo la cobertura de la noche. Puede encontrarlo en Twitter e Instagram donde comparte detalles de su historia de amor clandestina con JavaScript.