Abstract factory

by Artem

JavaScript

'use strict';

const __extends__ = (Parent, Child) => {
  Child.prototype = Object.create(Parent.prototype);
  Child.prototype.constructor = Child;
  Child.super = Parent;
};

const __getRandomId__ = () => Math.random().toString(36).slice(2);

const __makeConstructor__ = (factoryName, type) => {
  return function(id) {
    Reflect.defineProperty(this, type, {
      get() {
          return {
            id,
            type: `${factoryName} ${type}`
          };
        },
        set(newValue) {
          throw new TypeError(`Can't redefine ${type}`);
        }
    });
  };
};

const CarEngine = __makeConstructor__('Car', 'engine');
const CarSuspension = __makeConstructor__('Car', 'suspension');
const MotocycleEngine = __makeConstructor__('Motocycle', 'engine');
const MotocycleSuspension = __makeConstructor__('Motocycle', 'suspension');

const AbstractFactory = (function() {
  function AbstractFactory(brand) {
    if (this instanceof AbstractFactory) {
      throw new TypeError('Can\'t instantiate abstract constructor');
    }
  }
  AbstractFactory.prototype.createEngine = function(id) {
    throw TypeError('Unimplemented abstract method - createEngine');
  }
  AbstractFactory.prototype.createSuspension = function(id) {
    throw TypeError('Unimplemented abstract method - createSuspension');
  }

  return AbstractFactory;
}());

const CarFactory = (function(ParentFactory) {
  function CarFactory(brand) {
    Reflect.defineProperty(this, 'brand', {
      get() {
          return brand;
        },
        set(newBrand) {
          throw new TypeError('Can\'t redefine brand');
        }
    })
  }
  __extends__(ParentFactory, CarFactory);

  CarFactory.prototype.createEngine = function(id = __getRandomId__()) {
    return new CarEngine(id);
  };

  CarFactory.prototype.createSuspension = function(id = __getRandomId__()) {
    return new CarSuspension(id);
  };

  return CarFactory;

}(AbstractFactory));

const MotocycleFactory = (function(ParentFactory) {
 ...