Introduccion

1

Patrones Creacionales: Diseñando Objetos con Propósito

2

Patrones de Diseño Creacionales: Singleton y Factory

Singleton

3

Patrón Singleton: Cómo Garantizar Única Instancia de Clase en Java

4

Diagramas de Clases en UML para Patrones de Diseño

5

Patrones de Diseño en TypeScript: Singleton y Más

6

Patrones de diseño: Pros y contras del Singleton

Factory

7

Patrones de Diseño: Fábrica y Creación de Objetos

8

"Implementación de Patrón Factory en Programación Orientada a Objetos"

9

Implementación de Factory Method en JavaScript

10

Diferencias entre patrón Factory en JavaScript y TypeScript

11

Patrón Factory en Programación Orientada a Objetos

Abstract Factory

12

Patrón Abstract Factory en Producción de Coches

13

Patrones de Diseño: Implementación de Abstract Factory en Java

14

Programación Orientada a Objetos con JavaScript: Patron Abstract Factory

15

Diferencias clave entre clases e interfaces en TypeScript

16

Patrón Abstract Factory: Ventajas y Desventajas

Builder

17

Patrón Builder: Diseño de Objetos en Pasos Secuenciales

18

Patrón Builder: Diseño y Uso en Desarrollo de Software

19

Patrón Builder en Producción de Coches: JavaScript vs TypeScript

20

Transformación de Promesas en JavaScript a TypeScript

21

Patrones de Diseño: Uso del Patrón Builder en Java

Prototype

22

Clonación de objetos con el patrón Prototype

23

Clonación de objetos en JavaScript y TypeScript

24

Patrón Prototype: Clonación de Objetos en JavaScript

25

Diferencias entre Prototype en JavaScript y TypeScript

26

Clonación y Modificación de Objetos en JavaScript

Conclusiones

27

Patrones Creacionales en Diseño de Software

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Programación Orientada a Objetos con JavaScript: Patron Abstract Factory

14/27
Recursos

¿Cómo implementar el patrón AbstractFactory en JavaScript?

El patrón AbstractFactory es una robusta herramienta para la creación de familias de objetos relacionados. En este artículo, presentamos la implementación práctica de este patrón orientado a objetos en JavaScript, destacando su poder para disminuir el acoplamiento entre el código cliente y las instancias de los productos.

¿Cómo definir las clases base de los productos?

Para arrancar con el AbstractFactory, es fundamental definir las clases o interfaces de los productos base. En este caso, definimos dos productos: Mastodon y Rhino. Cada producto implementa un método useGPS, lo que garantiza que las implementaciones futuras deban realizar este método.

class MastodonCard {
    useGPS() {
        throw new Error("method not implemented");
    }
}

class RhinoCard {
    useGPS() {
        throw new Error("method not implemented");
    }
}

¿Cómo creamos las clases concretas de los productos?

El siguiente paso es establecer las clases concretas de los productos, que heredan de las clases base. Aquí creamos dos familias de vehículos: Sedan y Hatchback. Cada familia tiene su correspondiente implementación para Mastodon y Rhino.

class MastodonSedanCard extends MastodonCard {
    useGPS() {
        console.log("Sedan Mastodon GPS");
    }
}

class RhinoSedanCard extends RhinoCard {
    useGPS() {
        console.log("Sedan Rhino GPS");
    }
}

// Implementaciones similares para Hatchback

¿Qué es el abstract factory?

Posteriormente, se define el abstract factory, que establece un contrato para la creación de nuestras instancias de producto.

class AbstractFactory {
    createMastodon() {
        throw new Error("method not implemented");
    }

    createRhino() {
        throw new Error("method not implemented");
    }
}

¿Cómo implementar las fábricas concretas?

La clave del patrón está en las fábricas concretas que heredan del abstract factory. Definen las específicas versiones de los productos dentro de una familia.

class SedanCarFactory extends AbstractFactory {
    createMastodon() {
        return new MastodonSedanCard();
    }

    createRhino() {
        return new RhinoSedanCard();
    }
}

// Implementación similar para Hatchback

¿Cómo utilizar el patrón abstract factory?

Al emplear el patrón AbstractFactory, se inyecta la fábrica deseada, permitiendo crear objetos sin conocer su precisa clase. En el siguiente ejemplo utilizamos la fábrica Sedan y la Hatchback, y llamamos al método useGPS() de modo genérico.

function appCarFactory(factory) {
    const mastodon = factory.createMastodon();
    const rhino = factory.createRhino();

    mastodon.useGPS();
    rhino.useGPS();
}

const sedanFactory = new SedanCarFactory();
appCarFactory(sedanFactory);

const hatchbackFactory = new HatchbackCarFactory();
appCarFactory(hatchbackFactory);

¿Qué podemos concluir sobre la implementación en JavaScript?

Esta implementación del patrón AbstractFactory demuestra cómo se pueden crear distintos tipos de objetos relacionados sin comprometer el código cliente con clases específicas. Este patrón facilita que el diseño del software sea flexible, manejable y extensible.

Comparación con TypeScript y otras consideraciones

En proyectos complejos, utilizar TypeScript puede ofrecer ventajas adicionales, como la verificación temprana de tipos que ayudan a detectar errores. Continuaremos explorando las particularidades y beneficios de implementar este patrón en TypeScript en futuras entregas.

Esta metodología no sólo ilustra un claro entendimiento de los patrones de diseño, sino que también se erige como una herramienta esencial en el arsenal de cualquier desarrollador. Te animo a que implementes este patrón en tus propios proyectos y descubras por ti mismo sus beneficios. ¡Continúa aprendiendo y mejorando tus habilidades!

Aportes 10

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

No logró pensar en donde podría aplicar yo este patrón, en algunos empleos lo piden, pero como se vio en el curso anterior quizá es una exageración el pedirlo.

Pero con este patrón si entendí algo, los desarrolladores de zomboid son expertos en POO, porque puedo ver como este patrón ayudo a plantear ciertas mecánicas de ese videojuego, por ejemplo el “nuevo” sistema de autos en zomboid está claramente basado en este tipo de factories y zomboid es un juego mucho más complejos a nivel de mecánicas que la mayoría de juegos del mismo tipo.

En lo personal este patrón no me encanta. Factory ya usaba una capa de abstracción y este agrega otra capa (lo cuál lo hace complejo).
Además de eso, para agregar un producto nuevo (un coche en este caso), se necesitan agregar muchas cosas:

  • La creación del coche que siga el contrato de BaseCar (por cierto, no se agrego un BaseCar en el ejemplo de esta clase)
  • La creación de cada uno de los modelos de nuevo coche (Sedan y Hatchback en este caso)
  • Agregar un nuevo método en AbstractFactory para el nuevo producto
  • Agregar polimorfismo a cada subfactory del nuevo producto (SedanModelFactory & HatchbackModelFactory)
    .
    Son muchas cosas para agregar un nuevo producto. Aunque la buena noticia es que se siguen cumpliendo los principios de Responsabilidad Unica y de Open-Close

Comparto mi codigo hecho en TypeScript

// PASO 1
interface BaseCar {
    useGPS(): void
}

interface RhinoCar extends BaseCar {
}

interface MastodonCar extends BaseCar {
}

// PASO 2
class MastodonSedanCar implements MastodonCar {
    public useGPS(): void {
        console.log('[SEDAN] Mastodon GPS')
    }
}

class MastodonHatchbackCar implements MastodonCar {
    public useGPS(): void {
        console.log('[HATCHBACK] Mastodon GPS')
    }
}

class RhinoSedanCar implements RhinoCar {
    public useGPS(): void {
        console.log('[SEDAN] Rhino GPS')
    }
}

class RhinoHatchbackCar implements RhinoCar {
    public useGPS(): void {
        console.log('[HATCHBACK] Rhino GPS')
    }
}

// PASO 3
interface CarAbstractFactory {
    createMastodonCar(): MastodonCar
    createRhinoCar(): RhinoCar
}

// PASO 4
class SedanCarFactory implements CarAbstractFactory {
    public createMastodonCar(): MastodonCar {
        return new MastodonSedanCar()
    }

    public createRhinoCar(): RhinoCar {
        return new RhinoSedanCar()
    }
}

class HatchbackCarFactory implements CarAbstractFactory {
    public createMastodonCar(): MastodonCar {
        return new MastodonHatchbackCar()
    }

    public createRhinoCar(): RhinoCar {
        return new RhinoHatchbackCar()
    }
}

function appAbstractFactory(factory: CarAbstractFactory): void {
    const mastodon = factory.createMastodonCar()
    const rhino = factory.createRhinoCar()

    mastodon.useGPS()
    rhino.useGPS()
}

function createFactory(type: 'sedan' | 'hatchback'): CarAbstractFactory {
    const factories = {
        sedan: SedanCarFactory,
        hatchback: HatchbackCarFactory,
    }

    const Factory = new factories[type]
    return Factory
}

appAbstractFactory(createFactory('sedan'))
appAbstractFactory(createFactory('hatchback'))

Muy interesante este patrón de diseño, creería que es un patrón que podemos utilizar cuándo tenemos lógicas de negocio complejas.

Dejo mi codigo, a modo de experimento tengo algunas cosas distintas:

class NivusBase{
    model(){
    }
}

class TcrossBase{
    model(){
        throw Error("This method is not implemented");
    }
}

class NivusSedan extends NivusBase{
    model(){
        return "Nivus Senda 2023";
    }
}

class NivusHatback extends NivusBase{
    model(){
        return "Nivus Hatback 2023";
    }
}

class TcrossSedan extends TcrossBase{
    model(){
        return "Tcross Sedan 2023";
    }
}

class TcrossHatback extends TcrossBase{
    model(){
        return "Tcross Hatback 2023";
    }
}

class CarAbstractFactory {
    createNivus(){
        throw Error("This method is not implemented");

    }
    
    createTcross(){
        throw Error("This method is not implemented");

    }
}


class SedanCarFactory extends CarAbstractFactory{
    createNivus(){
        return new NivusSedan();

    }
    createTcross(){
        return new TcrossSedan();
    }

}

class HatbackCarFactory extends CarAbstractFactory{
    createNivus(){
        return new NivusHatback();

    }
    createTcross(){
        return new TcrossHatback();
    }
}

function appAbstractFactory(factory){
    return new factory()
}

carSedanFactory = appAbstractFactory(SedanCarFactory);
carHatbackFactory = appAbstractFactory(HatbackCarFactory);

console.log(carSedanFactory.createNivus().model());
console.log(carSedanFactory.createTcross().model());

console.log(carHatbackFactory.createNivus().model());
console.log(carHatbackFactory.createTcross().model());

En el paso 4 noté que faltó heredar de la clase CarAbstractFactory para cumplir con lo que nos dice este paso: Create concrete factories that implements/inherits from the abstract factory behaviour and implements all the products creation methods. ```js class SedanCarFactory extends CarAbstractFactory { /** * @override createMastodon() method * @returns MastodonSedanCar */ createMastodon() { return new MastodonSedanCar(); } /** * @override createRhino() method * @returns RhinoSedanCar */ createRhino() { return new RhinoSedanCar(); } } ```

Cada vez más preparados para ir a aplicar en Tesla 😎

como sacas los multiples cursores para editar varias lineas de codigo al tiempo ? s no tengo mouse :V
Un poco díficil de entender en la última parte, en particular en el siguiente fragmento de código: ```js function createFactory(type) { // .... const Factory = factories[type]; return new Factory(); } ```Creo que se debe especificar que la constante Factory, ahora contiene una referencia a la clase o función constructora que fue seleccionada en el paso anterior. Luego se crea una nueva instancia de esa clase o función constructora usando `new Factory()`.
El que no haya extendido las clases `HatchbackCarFactory` y `SedanCarFactory` a `CarAbstractFactory` es un error? Si no fuese un error, no coincidiria con el diagrama de la clase anterior.