Patrón creacional Abstract Factory(JavaScript) - fapaccha/Dise-o-dirigido-por-el-modelo GitHub Wiki

Abstract Factory(JavaScript)

Este patrón se le considera como super-factory, ya que de manera interna tiene dos o más Factory Method Primero generamos la clase principal Vehicle, donde va a tener sus propiedades y métodos:

IM1

Podemos observar que tenemos una clase principal Vehicle y que tenemos 8 subclases (4 para carros, 4 para motos), para llegar al patrón de Abstract Factory, primero debemos usar el Factory Method:

class Vehicle {
  constructor(type, model) {
    this._model = model;
    this._type = type;
  }
   get model(){
    return this._model;
  }
  get type(){
    return this._type;
  }
  description(){
    return `I am of type "${this.type}" and my model is "${this.model}!"`
  } 
}

export default Vehicle;

Im2

Lo que hacemos es crear un Factory para cada uno de los tipos MotorcycleFactory y CarFactory, donde cada uno de ellos va a hacer la instancia del objeto dependiendo de las propiedades que se le pasen; hasta aquí hemos cumplido con el patrón de Factory Method, ahora lo que vamos a hacer es crear un super-factory FactoryProvider, para que esté a su vez mande a llamar los factory MotorcycleFactory, CarFactory.

im3

import Vehicle from "./Vehicle";

class MotorcycleType1 extends Vehicle {
  constructor() {
    super("motorcycle", "deportiva");
  }
}

class MotorcycleType2 extends Vehicle {
  constructor() {
    super("motorcycle", "motoneta");
  }
}

class MotorcycleType3 extends Vehicle {
  constructor() {
    super("motorcycle", "moto");
  }
}

class MotorcycleType4 extends Vehicle {
  constructor() {
    super("motorcycle", "cuatrimoto");
  }
}

export { MotorcycleType1, MotorcycleType2, MotorcycleType3, MotorcycleType4 };
import Vehicle from "./Vehicle";

class CarType1 extends Vehicle {
  constructor() {
    super("car", "super");
  }
}

class CarType2 extends Vehicle {
  constructor() {
    super("car", "deportivo");
  }
}

class CarType3 extends Vehicle {
  constructor() {
    super("car", "combi");
  }
}

class CarType4 extends Vehicle {
  constructor() {
    super("car", "clasico");
  }
}

export { CarType1, CarType2, CarType3, CarType4 };

Generamos dos clases Factory MotorcycleFactory y CarFactory, donde dependiendo del modelo model que se la mande es la instancia de objeto que va a realizar:

import {
  MotorcycleType1,
  MotorcycleType2,
  MotorcycleType3,
  MotorcycleType4
} from "./Motorcycle";

class MotorcycleFactory {
  create(model) {
    switch (model) {
      case "deportiva":
        return new MotorcycleType1();
      case "motoneta":
        return new MotorcycleType2();
      case "moto":
        return new MotorcycleType3();
      case "cuatrimoto":
        return new MotorcycleType4();
      default:
        console.log("Model not found ", model);
        break;
    }
  }
}

export default MotorcycleFactory;

import { CarType1, CarType2, CarType3, CarType4 } from "./Car";

class CarFactory {
  create(model) {
    switch (model) {
      case "super":
        return new CarType1();
      case "deportivo":
        return new CarType2();
      case "combi":
        return new CarType3();
      case "clasico":
        return new CarType4();
      default:
        console.log("Model not found ", model);
        break;
    }
  }
}

export default CarFactory;

Y por último creamos el super-factory que es la clase FactoryProvider, donde va a mandar a llamar a las clases Factory, dependiendo del tipo type que se le mande:

import CarFactory from "./CarFactory";
import MotorcycleFactory from "./MotorcycleFactory";

class FactoryProvider {
  createType(type) {
    if (type === "car") {
      return new CarFactory();
    } else if (type === "motorcycle") {
      return new MotorcycleFactory();
    } else {
      console.log("Error type");
    }
  }
}

export default FactoryProvider;