Skip to content

Instantly share code, notes, and snippets.

@DmitriiNazimov
Last active May 1, 2024 15:46
Show Gist options
  • Select an option

  • Save DmitriiNazimov/a7670df68154d28e3e9de117bfa35293 to your computer and use it in GitHub Desktop.

Select an option

Save DmitriiNazimov/a7670df68154d28e3e9de117bfa35293 to your computer and use it in GitHub Desktop.
[JS ES6 Паттерн СТРОИТЕЛЬ (builder)] #js #ES6 #ООП #Паттерны
/**
*
* ПАТТЕРН СТРОИТЕЛЬ (builder (композиционный конструктор обьекта))
*
* Паттерн СТРОИТЕЛЬ - это порождающий паттерн проектирования, который позволяет создавать сложные объекты пошагово.
* Строитель даёт возможность использовать один и тот же код строительства для получения разных представлений объектов.
* Применение: Паттерн Строитель нужен, если объект может существовать в разных вариациях или процесс
* инстанцирования состоит из нескольких шагов.
* В этом случае есть три варианта:
* - огромный конструктор(фабрика) со множеством if/else в котором легко запуться и который тяжело понять
* - плодить кучу подклассов для всех вариантов (это наверное еще хуже первого варианта)
* - паттерн строитель (предлагает разбить процесс конструирования объекта на отдельные шаги (например, построитьСтены,
* вставитьДвери и другие). Чтобы создать объект, вам нужно поочерёдно вызывать методы строителя. Строителей может быть
* несколько разных вариантов, но у них общий интерфейс.)
*/
class abstract_Products { // абстрактный класс продуктов
constructor(builder) {
this.size = builder.size
this.cheeze = builder.cheeze || false
this.pepperoni = builder.pepperoni || false
this.lettuce = builder.lettuce || false
this.tomato = builder.tomato || false
}
}
//конкретные продукты
class Burger extends abstract_Products {
constructor(builder) {
super(builder);
this.breadType = builder.breadType;
this.meatType = builder.meatType;
}
}
class Pizza extends abstract_Products {
constructor(builder) {
super(builder);
this.doughType = builder.doughType;
}
}
class ProductBuilder { // абстрактный класс строителя. Методы м.б. как асбтрактными, так и описанными.
constructor(size) {
this.size = size
}
addPepperoni() {
this.pepperoni = true
return this
}
addLettuce() {
this.lettuce = true
return this
}
addCheeze() {
this.cheeze = true
return this
}
addTomato() {
this.tomato = true
return this
}
getProduct() { // этот метод абстрактный, т.к. всегда разный
throw new Error(`В ${this.constructor.name} не описан метод getProduct()`)
}
}
class BurgerBuilder extends ProductBuilder {
constructor(size) {
super(size);
}
setBreadType (bread) {
this.breadType = bread
return this
}
setMeatType (meat) {
this.meatType = meat
return this
}
getProduct() {
if (!this.breadType) {
throw new Error(`${this.constructor.name} получил некорректное значение breadType`)
} else if (!this.meatType) {
throw new Error(`${this.constructor.name} получил некорректное значение meatType`)
}
return new Burger(this)
}
}
class PizzaBuilder extends ProductBuilder {
constructor(size) {
super(size);
}
setDoughType (doughType) {
this.doughType = doughType;
return this
}
getProduct() {
if (!this.doughType) {
throw new Error(`${this.constructor.name} получил некорректное значение doughType`)
}
return new Pizza(this)
}
}
// Клиентский код. При необходимости можно его поместить в отдельный класс - Director
const burger = (new BurgerBuilder(14))
.addPepperoni()
.addLettuce()
.addTomato()
.setBreadType('black')
.setMeatType('chicken')
.getProduct()
console.log(burger);
const pizza = (new PizzaBuilder(32))
.addPepperoni()
.addCheeze()
.addLettuce()
.addTomato()
.setDoughType('slim')
.getProduct()
console.log(pizza);
const slimBurger = (new BurgerBuilder(14)) // делаем еще один бургер, но чтобы результат был другим
.setBreadType('white')
.setMeatType('beef')
.getProduct()
console.log(slimBurger);
@xreider
Copy link
Copy Markdown

xreider commented May 3, 2022

Помоги типизировать, пожалуйста

Песочница

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment