Строитель — это один из Порождающих шаблонов, который помогает вам разобраться в том, как создаются объекты. Вам следует уделять пристальное внимание методам создания объектов, которые могут вылиться в серьезные проблемы дизайна, если вы ими пренебрегаете.
Начните здесь, если вы новичок в шаблонах проектирования в JavaScript
Примеры из реальной жизни
Представьте, что вам нужно собрать из крошечных деталей лего нечто, похожее на дом. Есть несколько разных способов сгруппировать их в различные представления.
Базовый дом будет иметь дверь, ноль или более окон и крышу с окружающими стенами. Некоторые могут даже иметь гараж, а некоторые — бассейн. Мы хотели бы, чтобы процесс был более простым и гибким, чтобы можно было вносить изменения.
Пошаговая сборка деталей лего, имеющихся в вашем распоряжении, составляет суть паттерна Строитель.
Таким образом, объекты конструируются в соответствии с последовательностью шагов один за другим, а не достигаются сразу.
Объекты JavaScript - это набор свойств и методов. Свойства - это поля или переменные, связанные с объектом. А методы — это функции, которые вы собираетесь вызывать для управления полями. Свойства объектов тесно связаны друг с другом, по крайней мере, в худшем случае семантически.
JavaScript предоставляет множество способов создания объектов.
Инициализатор объекта
Самый распространенный метод создания объекта в JavaScript - это нотация «объектный литерал».
const employee = {
firstName: 'Sam',
lastName: 'Greene',
id: '12340987',
phone: '07123456789'
};
где firstName, lastName, id и phone - это свойства объекта с именем employee.
Конструктор
В качестве альтернативы мы можем использовать конструктор для создания нескольких экземпляров похожих объектов с помощью ключевого слова new
.
class Employee {
constructor(fname, lname, id, ph) {
this.firstName = fname;
this.lastName = lname;
this.id = id;
this.ph;
}
};
const employee1 = new Employee('Sam', 'Greene', 12340987, '07123456789');
const employee2 = new Employee('Nate', 'Tyson', 56478390, '07987654321');
Использование Object.create
Object.create() - это встроенная функция, которую вы можете использовать для создания нескольких экземпляров объекта. Это позволяет вам передать объект шаблона в качестве входных данных, таким образом, выбирая прототип для объектов по желанию, без конструктора.
const Employee = {
isAdmin: false,
getRole: function() {
return this.isAdmin ? 'Admin' : 'RegularEmp';
};
};
const emp1 = Object.create(Employee);
emp1.getRole(); //'RegularEmp'
const emp2 = Object.create(Employee);
emp2.isAdmin = true;
emp2.getRole(); //'Admin'
В этом примере и emp1, и emp2 унаследовали метод getRole. Как только вы установите для параметра isAdmin значение true, роль emp2 изменится на Admin.
Эта проблема
Похоже, что уже существует несколько способов создания объектов в JavaScript. Зачем нам изобретать что-то другое?
Рассмотрим два важных вопроса:
- Что делать, если вам нужно создать сложный объект, содержащий слишком много полей и свойств?
- Что, если вам нужно создать несколько экземпляров почти одного и того же объекта?
Литерал объекта - не лучший выбор, поскольку он не помогает повторно использовать код. Каждый раз, когда вам нужен новый объект, вам придется снова и снова перечислять все его поля.
Конструктор до некоторой степени решил бы проблему, но это было бы громоздко. Вам нужно будет запомнить входные данные для него, некоторые из которых являются обязательными, а другие нет.
Паттерн Строитель
Что, если бы у вас был способ решить только две вышеупомянутые проблемы, скрывая внутреннее представление от всех, кто его использует?
В реальной жизни объекты окружают нас повсюду. И вы можете сравнивать с ними объекты JavaScript.
Например, автомобиль бывает разного цвета или с разным количеством сидений. В доме может быть разное количество дверей, окон и дымоходов. Различия есть везде, но есть некоторые сходства.
Шаблон Builder позволяет упростить создание сложного объекта, отделив его от его представления.
Этот шаблон упрощает создание объекта, выполняя процесс поэтапно, а также инкапсулируя (скрывая) детали реализации этих шагов.
Давайте посмотрим, как выглядит гибкий дизайн для простого конструктора OTG и как он развивается с помощью паттерна Builder.
Создание OTG с использованием шаблона проектирования Builder
Должна быть предусмотрена возможность создания OTG различных цветов, моделей, цен и функций. Некоторые из них рассчитаны на высокую температуру и имеют хороший интервал выбора таймера. Например, младшие модели идут с низкотемпературными настройками и таймером по умолчанию.
Шаг 1. Класс OTG
Простой класс для OTG здесь имеет конструктор JS, который принимает четыре параметра. У каждого экземпляра OTG есть заголовок по умолчанию, переопределяемая температура и выбор времени, которые по умолчанию установлены на 150 и 30 соответственно.
class OTG {
constructor(model, color, maxTemperature, maxTimeSelection) {
this.model = model;
this.title = 'OTG';
this.color = color;
this.maxTemperature = maxTemperature || 150;
this.maxTimeSelection = maxTimeSelection || 30;
}
}
const redOTG = new OTG('LG', 'red');
const highTempOTG = new OTG('LG', 'black', 200);
const highendTimeOTG = new OTG('LG', 'red', '150', '60');
Приведенный выше код пока выглядит нормально. Но с этим есть проблема.
Представьте, что вам нужно создать несколько выборок экземпляров OTG. Будет сложно отслеживать параметры и их порядок в конструкторе. Кроме того, иногда нет необходимости отправлять определенные необязательные параметры.
Шаг 2. Создайте класс строителя
Давайте посмотрим, как можно избежать забивания конструктора минимальными параметрами.
class OTGBuilder {
constructor(model, color) {
this.model = model;
this.title = 'OTG';
this.color = color;
}
}
Здесь класс OTGBuilder отвечает за создание экземпляров класса OTG. Но пока этого не происходит. На данный момент он просто захватывает базовую модель и цвет полей.
Эти поля являются обязательными, поэтому мы включаем их прямо в конструктор.
Шаг 3. Добавьте необязательные параметры как отдельные функции
Вы, наверное, заметили, что поля maxTemperature
и maxTimeSelection
нельзя настроить с помощью конструктора.
Эти свойства необязательны, и мы создадим отдельные функции для их установки.
class OTGBuilder {
constructor(model, color) {
this.model = model;
this.title = 'OTG';
this.color = color;
}
setMaxTemperature(temp) {
this.maxTemperature = temp;
return this;
}
setMaxTimeSelection(maxTime) {
this.maxTimeSelection = maxTime;
return this;
}
}
Необходимо добавить return this;
, чтобы убедиться, что мы можем использовать цепной вызов при работе с шаблоном проектирования Builder.
const otg = new OTGBuilder('MorphyRichards', 'Black')
.setMaxTemperature(250)
.setMaxTimeSelection(60);
Шаг 4. Сборка
Единственная оставшаяся проблема заключается в том, что объект otg
еще не является подходящим OTG. Это экземпляр класса OTGBuilder. И вам нужно реализовать последний шаг процесса — метод build ().
class OTGBuilder {
constructor(model, color) {
this.model = model;
this.title = 'OTG';
this.color = color;
}
setMaxTemperature(temp) {
this.maxTemperature = temp;
return this;
}
setMaxTimeSelection(maxTime) {
this.maxTimeSelection = maxTime;
return this;
}
build() {
return new OTG(this.model, this.color,
this.maxTemperature, this.maxTimeSelection);
}
}
Теперь вы можете вызвать метод build(), когда будете готовы создать свой OTG.
const basicOTG = new OTGBuilder('MorphyRichards', 'Black')
.setMaxTemperature(250)
.setMaxTimeSelection(60)
.build();
При желании вы всегда можете пропустить шаги по установке дополнительных параметров.
const default = new OTGBuilder('Generic OTG', 'White')
.build();
Для свойств maxTemperature и maxTimeSelection по умолчанию будут заданы значения 150 и 30, если вы не перезапишете их с помощью setMaxTemperature и setMaxTimeSelection.
Получите мою бесплатную электронную книгу, чтобы подготовиться к техническому собеседованию, или начните учить Full-Stack JavaScript