Comprender las ventajas y limitaciones del patrón factory es fundamental para tomar decisiones de diseño acertadas. Este patrón de creación permite construir objetos sin acoplar el código a implementaciones concretas, y conocer sus fortalezas y debilidades te ayudará a saber exactamente cuándo conviene implementarlo y cuándo es mejor optar por una solución más simple.
¿Qué beneficios aporta el patrón factory a tu código?
El primer gran beneficio es que evita un acoplamiento alto entre los elementos creadores y los productos [0:18]. Las fábricas concretas retornan un producto base en sus métodos de fabricación, pero internamente devuelven un producto concreto. Esto significa que el resto del código no necesita conocer los detalles de construcción; simplemente consume lo que la fábrica le entrega.
El segundo punto está asociado al principio de responsabilidad única, parte de los conocidos principios SOLID [1:08]. La creación de productos sucede en un único punto:
- Los métodos de creación solo crean productos y los retornan.
- No hay efectos secundarios ni lógica oculta.
- Si necesitas revisar cómo se construye un objeto, sabes exactamente dónde buscar: la clase fábrica concreta y su método de creación.
El tercer beneficio tiene que ver con la extensibilidad [1:52]. Agregar nuevos productos no requiere modificar el código existente, sino extenderlo. No tocas las clases de productos ni las fábricas que ya funcionan. Solo agregas un nuevo producto y una nueva clase fábrica. Puedes incorporar cualquier elemento hoy o mañana de forma suave y predecible.
¿Cuáles son las desventajas del patrón factory?
No todo es favorable. La primera desventaja es la generación de demasiado código genérico [2:20]. Cada nuevo producto requiere una nueva fábrica. Si necesitas crear diecisiete productos nuevos, estarías hablando de treinta y cuatro clases. Eso puede volverse difícil de mantener.
La segunda desventaja son las muchas abstracciones [2:45]. A veces no es necesario crear clases o elementos que funcionen sobre otros. Una función sencilla que reciba un tipo y retorne el producto correcto podría ser la solución más práctica en términos de costo y tiempo. No hay nada malo en ello; lo importante es elegir la herramienta adecuada para cada situación.
¿Cuándo conviene usar el patrón factory?
Hay tres escenarios claros donde este patrón brilla [3:12]:
- Cuando no sabes cuántos productos diferentes habrá. Defines un comportamiento similar para las fábricas y cualquier producto nuevo que llegue será fácil de integrar.
- Cuando necesitas desacoplar el uso de los productos con su creación. Si tu código depende de un producto concreto en muchos lugares, introducir otro implicaría cambios masivos. Con el patrón factory, dependes de abstracciones en lugar de implementaciones concretas.
- Cuando quieres extender bibliotecas o frameworks. Algunas bibliotecas de UI exponen interfaces para componentes como botones. Si no tienen el tipo que necesitas, puedes implementar tu propio componente que cumpla ese contrato y la biblioteca lo aceptará como parte de su repertorio.
¿Cómo se aplica el patrón factory en frameworks reales?
Un ejemplo concreto es Nest.js [4:52], un framework para construir aplicaciones del lado del servidor basado en convenciones. Internamente utiliza Express como web framework, pero permite cambiarlo por Fastify. La clave está en que ambos implementan un comportamiento similar a través de adaptadores.
Cuando le pasas un adaptador de Express o de Fastify a Nest.js, el framework verifica que cumpla una interfaz definida y, si la cumple, puede utilizar los métodos establecidos en ese contrato. Eso es el principio de depender de abstracciones y no de implementaciones concretas aplicado en producción.
¿Cómo construir tu propio adaptador HTTP?
El reto propuesto consiste en crear un adaptador HTTP personalizado [5:48], como si fueras a construir tu propio web framework e insertarlo dentro de Nest.js. La estructura incluye:
- Un
HttpAdapterFactory con un método makeAdapter.
- Un
HttpAdapter con un constructor que recibe una cadena y retorna un objeto.
- Métodos obligatorios:
get, post, put y delete.
En el repositorio encontrarás verificaciones que validan si tu adaptador cumple la estructura y la implementación de todos los métodos. Si todas pasan, habrás logrado implementar tu propio adaptador funcional. ¿Aceptas el reto?