Синглтон шаблон | Заводской узор | Шаблон конструктора

Темы

  • Синглтон шаблон
  • Заводской узор
  • Заводской шаблон против шаблона конструктора

Шаблон Singleton (использует Redux или React Context)

  • Шаблон проектирования Singleton предоставляет один экземпляр, который может использоваться несколькими компонентами.
  • Singleton Pattern можно считать основой глобальных библиотек управления состоянием, таких как Redux или React Context.
  • Это шаблон, который ограничивает класс созданием только одного экземпляра.
  • К ним можно получить глобальный доступ, и они действуют как единая точка доступа для доступа к глобальному состоянию.
let instance;
let globalState = {
  color: ""
};

class StateUtility {
  constructor() {
    if (instance) {
      throw new Error("New instance cannot be created!!");
    }
    instance = this;
  }
  getPropertyByName(propertyName) {
    return globalState[propertyName];
  }
  setPropertyValue(propertyName, propertyValue) {
    globalState[propertyName] = propertyValue;
  }
}
let stateUtilityInstance = Object.freeze(new StateUtility());
export default stateUtilityInstance;
  • Мы следим за тем, чтобы не раскрывать файл globalState. Мы раскрываем их, используя методы класса StateUtility. Таким образом, мы защищаем глобальное состояние от прямого изменения.
  • Наконец, мы создаем экземпляр класса следующим образом: let stateUtilityInstance = Object.freeze(new StateUtility());.
  • Мы использовали Object.freeze, чтобы ни один другой класс/компонент/модуль не мог изменить открытый stateUtilityInstance.

Заводской шаблон (Заводской шаблон против конструкторов) —

  • Фабрика — это объект, класс или функция в парадигме функционального программирования для создания объектов.
  • Фабричный методсоздает новые объекты в соответствии с указаниями клиента. Одним из способов создания объектов в JavaScript является вызов функции-конструктора с оператором new.
  • Шаблон проектирования Factory используется, когда у нас есть суперкласс с несколькими подклассами, и на основе входных данных нам нужно вернуть один из подклассов. Этот шаблон снимает с себя ответственность за создание экземпляра класса из клиентской программы в класс фабрики.
  • Классы делегируют ответственность одному из нескольких вспомогательных подклассов, и вы хотите локализовать знания о том, какой вспомогательный подкласс является делегатом.
  • Фабричные методы часто используются в приложениях, которые управляют, поддерживают или манипулируют наборами объектов, которые отличаются друг от друга, но в то же время имеют много общих характеристик (т. е. методов и свойств).
  • Фабричный шаблон может использовать внутри конструктор или класс. Но фабричный шаблон предпочтительнее в тех случаях, когда процесс создания объекта зависит от динамических факторов, например, когда мы хотим динамически создавать подклассы.
  • Factory предоставляет нам гибкий и многоразовый механизм создания объектов.
// creates factory function
function vehicleFactory (manufacturer, plateNO) {
    return  {
        manufacturer,
        plateNO,
        startEngine () {
            console.log("reving engine")
        },
        drive () {
            console.log("driving car...")
        }
    }
}
 
const Vehicle1 = vehicleFactory("Toyota", 12345);
console.log(Vehicle1) 
// prints 
//{
//  manufacturer: 'Toyota',
//  plateNO: 12345,
//  startEngine: [Function: startEngine],
//  drive: [Function: drive]
//}
  
const Vehicle2 = vehicleFactory("Ford", 13345);
console.log(Vehicle2) 
// prints 
// {
//  manufacturer: 'Ford',
//  plateNO: 13345,
//  startEngine: [Function: startEngine],
//  drive: [Function: drive]
// }

Примеры,

  • Фабричный шаблон способствует повторному использованию кода за счет повторного использования методов StartEngine, driveVehicle и stopEngine.
class Car {
    constructor(options) {
        this.wheels = options.wheels || 4;
        this.doors = options.doors || 4;
        this.color = options.color || "silver"; 
    }
}

class Truck {
    constructor(options) {
        this.wheels = options.wheels || 6;
        this.doors = options.doors || 2;
        this.color = options.color || "red"; 
    }
}


class Factory {

    create = (options, vehicleType) => {

        if(!vehicleType) {
            return "unable to make vehicle. Please specify a vehicle type and tryagain!"
        }

        let vehicle;
        
        if (vehicleType === "car") {
            vehicle = new Car(options);
        } else if (vehicleType === "truck") {
            vehicle = new Truck(options);
        } 

  
        vehicle.vehicleType = vehicleType;

        vehicle.startEngine = ()=> console.log(`Reving ${vehicleType} engine`);

        vehicle.driveVehicle = ()=> console.log(`Driving ${vehicleType}...`);

        vehicle.stopEngine = ()=> console.log(`Stop ${vehicleType} engine`);

        return vehicle;
    }
 
};

const vehicleFactory = new Factory();

const car = vehicleFactory.create({
    wheels: 4,
    doors: 2,
    color: "black",
}, "car");

console.log(car)
console.log(car.startEngine())
console.log(car.driveVehicle())

// prints:
//Car {
//  wheels: 4,
//  doors: 4,
//  color: 'silver',
//  vehicleType: 'car',
//  startEngine: [Function],
//  driveVehicle: [Function],
//  stopEngine: [Function]
//}

// Reving car engine
// Driving car...

const truck = vehicleFactory.create({
    wheels: 4,
 doors: 2,
 color: "yellow",
}, "truck")

console.log(truck)
console.log(truck.startEngine())
console.log(truck.stopEngine())
// prints
//Truck {
//  wheels: 4,
//  doors: 2,
//  color: 'yellow',
//  vehicleType: 'truck',
//  startEngine: [Function],
//  driveVehicle: [Function],
//  stopEngine: [Function]
//}

// Reving truck engine
// Stop truck engine
  • Благодаря шаблону factory наш код также легко поддерживать, поэтому, если бизнес расширяется и завод начинает производить новые виды транспортных средств, мы можем легко изменить нашу реализацию, чтобы справиться с этим, как показано ниже:
class Car {
    constructor(options) {
        this.wheels = options.wheels || 4;
        this.doors = options.doors || 4;
        this.color = options.color || "silver"; 
    }
}

class Truck {
    constructor(options) {
        this.wheels = options.wheels || 6;
        this.doors = options.doors || 2;
        this.color = options.color || "red"; 
    }
}

class Bus {
    constructor(options) {
        this.wheels = options.wheels || 4;
        this.doors = options.doors || 4;
        this.color = options.color || "white"; 
    }
}

class Motorcycle {
    constructor(options) {
        this.wheels = options.wheels || 2;
        this.doors = options.doors || 0;
        this.color = options.color || "Black"; 
    }
}


class Factory {

    create = (options, vehicleType) => {

        if(!vehicleType) {
            return "unable to make vehicle. Please specify a vehicle type and tryagain!"
        }

        let vehicle;
        
        if (vehicleType === "car") {
            vehicle = new Car(options);
        } else if (vehicleType === "truck") {
            vehicle = new Truck(options);
        } else if (vehicleType === "bus") {
            vehicle = new Bus(options);
        } else if (vehicleType === "motorcycle") {
            vehicle = new Motocycle(options);
        }

  
        vehicle.vehicleType = vehicleType;

        vehicle.startEngine = ()=> console.log(`Reving ${vehicleType} engine`);

        vehicle.driveVehicle = ()=> console.log(`Driving ${vehicleType}...`);

        vehicle.stopEngine = ()=> console.log(`Stop ${vehicleType} engine`);

        return vehicle;
    }
 
};

const vehicleFactory = new Factory();

const bus = vehicleFactory.create({
    wheels: 4,
    doors: 4,
    color: "yellow",
}, "bus");

console.log(bus)
console.log(bus.startEngine())
console.log(bus.driveVehicle())

// prints:
// Bus {
//  wheels: 4,
//  doors: 4,
//  color: 'yellow',
//  vehicleType: 'bus',
//  startEngine: [Function],
//  driveVehicle: [Function],
//  stopEngine: [Function]
//}

// Reving bus engine
// Driving bus...

const bike = vehicleFactory.create({
    wheels: 2,
 doors: 0,
 color: "red",
}, "motorcycle")

console.log(bike)
console.log(bike.startEngine())
console.log(bike.stopEngine())
// prints
// Motorcycle {
//  wheels: 2,
//  doors: 0,
//  color: 'red',
//  vehicleType: 'bike',
//  startEngine: [Function],
//  driveVehicle: [Function],
//  stopEngine: [Function]
//}

// Reving motorcycle engine
// Stop motorcycle engine

Больше примеров,

var Factory = function () {
    this.createEmployee = function (type) {
        var employee;

        if (type === "fulltime") {
            employee = new FullTime();
        } else if (type === "parttime") {
            employee = new PartTime();
        } else if (type === "temporary") {
            employee = new Temporary();
        } else if (type === "contractor") {
            employee = new Contractor();
        }

        employee.type = type;

        employee.say = function () {
            console.log(this.type + ": rate " + this.hourly + "/hour");
        }

        return employee;
    }
}

var FullTime = function () {
    this.hourly = "$12";
};

var PartTime = function () {
    this.hourly = "$11";
};

var Temporary = function () {
    this.hourly = "$10";
};

var Contractor = function () {
    this.hourly = "$15";
};

function run() {

    var employees = [];
    var factory = new Factory();

    employees.push(factory.createEmployee("fulltime"));
    employees.push(factory.createEmployee("parttime"));
    employees.push(factory.createEmployee("temporary"));
    employees.push(factory.createEmployee("contractor"));

    for (var i = 0, len = employees.length; i < len; i++) {
        employees[i].say();
    }
}

Заводской шаблон против конструкторов

  • Шаблон конструктора и шаблон фабрики похожи, поскольку это шаблоны создания объектов, возвращающие новый объект.
  • Метод Factory может возвращать уже созданный объект, в отличие от конструктора, который всегда создает новый экземпляр.
  • Фабричные методы продвигают идею кодирования с использованием интерфейса, а затем реализации, что приводит к более гибкому коду, но конструктор привязывает ваш код к конкретной реализации.
  • Причины использования конструкторов: мы используем конструкторы для инициализации объекта с состоянием по умолчанию или начальным состоянием. Значения по умолчанию для примитивов могут не соответствовать вашим требованиям. Другая причина использования конструктора заключается в том, что он информирует о зависимостях.
  • Причина использования Factory: шаблон метода Factory позволяет подклассам выбирать тип создаваемых объектов. Это способствует слабой связи, устраняя необходимость привязки классов, специфичных для приложения, к коду.
const vehicleOptions = {type: "cars", color: "white", doors: 4, wheels: 4}

// factory pattern
function Factory(options) {
  let factory = {};
  factory.type = options.type;
  factory.color = options.color;
  factory.wheels = options.wheels;
  factory.doors = options.doors;
  
  return factory;
}

const vehicle = Factory(vehicleOptions);

// constructor pattern
function ConstructorPattern(options) {
  this.type = options.type;
  this.color = options.color
  this.doors = options.doors;
  this.wheels = options.wheels;
}

const vehicle2 = new ConstructorPattern(vehicleOptions);

console.log("factory car", vehicle)
// prints { type: 'cars', color: 'white', wheels: 4, doors: 4 }

console.log("constructor car", vehicle2)
// prints { type: 'cars', color: 'white', wheels: 4, doors: 4 }

Когда использовать заводской шаблон

Шаблон Factory может быть особенно полезен при применении в следующих ситуациях:

  • Когда настройка нашего объекта или компонента связана с высоким уровнем сложности.
  • Когда нам нужно легко генерировать разные экземпляры объектов в зависимости от среды, в которой мы находимся.
  • Когда мы работаем со многими небольшими объектами или компонентами, которые имеют одни и те же свойства.
  • При составлении объектов с экземплярами других объектов, которым для работы нужно только соответствие контракту API (он же утиный ввод). Это полезно для развязки.

Спасибо за прочтение

Я знаю, что всегда есть что улучшить. Пожалуйста, поделитесь своими мыслями

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите потрясающую работу