Шаблони дизайну - Швидкий посібник із шаблону Builder.

Шаблон Builder - це креативний шаблон дизайну, який керує побудовою складних об'єктів поетапно (або цеглою за цеглою). Це, мабуть, найпростіший шаблон, який можна помітити, якщо існуючий код потребує такого дизайну. Шаблон Builder дозволяє створювати різні представлення об'єкта за допомогою одного і того ж будівельного коду.

Шаблон будівельника класифікується у шаблонах креативного дизайну, що стосується створення класів / об'єктів. Точніше, як ефективно використовувати успадкування (шаблони створення класів) або делегування (шаблони створення об'єктів). [за шаблонами дизайну пояснено просто]

Приклад. Почнемо з прикладу моєї улюбленої теми. Їжа !! Точніше приклад буде про піцу. Піца розділена на три шари, тісто, соус і начинка. Тепер давайте запитаємо себе, як би ми “сконструювали” предмет піци, вибираючи різні начинки та різноманітні соуси.

Питання перед розробкою рішення цієї проблеми:

  • Як би виглядав конструктор класу Піца?
  • Чи повинні ми мати кілька конструкторів для перевантаження з параметрами для всіх комбінацій, таких як соуси, начинки плюс соуси тощо? Що робити, якщо у нас також є різні види тіста?
  • Що, якщо згодом ми вирішимо додати сир або різні види сиру? Це було б легко здійснити? Що щодо залежностей від існуючого коду?
  • Чи просто у нас є конструктор за замовчуванням, який створює "звичайну піцу"? Хіба це не змусило б клієнта зателефонувати відповідно до кількох сетерів? Це безпечно? Що робити, якщо клієнт забуде і тоді ми відправляємо звичайну піцу клієнту?

Вирішенням усіх цих питань є модель побудови. Нам потрібен "будівельник", щоб побудувати піцу поетапно. У той же час, клієнт буде безпечно "замовити" конкретну піцу і доручити будівельникові її створити для нього.

Крок 1 - Ключові слова

  1. Представлення: Об'єкт може мати різні зображення. Наприклад, піца може мати томатні начинки з моцарелла, а інша репрезентація піци - з грибами та пармською шинкою.
  2. Код будівництва: Об'єкти можна побудувати різними способами, наприклад, використовуючи конструктори. Конструктори можуть бути перевантажені, вони мають однакову назву (назва класу), але різну кількість / типи аргументів. Залежно від кількості та типу переданих аргументів викликається конкретний конструктор.

Легко потрапити в пастку наявності класу численних конструкторів, де кожен приймає різну кількість параметрів. Розробник змушений інстанціювати клас правильним поєднанням параметрів для кожної ситуації. Ця проблема має назву, вона є популярним анти-шаблоном, який називається конструктором телескопії, а модель для конструктора - це вирішення для нього. Давайте спростимо модель Builder прямо, прямо кажучи:

Основна мета структури Builder - мати мінімальну кількість конструкторів, що перевантажують, для підтримки конструкції декількох уявлень об'єкта.

Крок 2 - Діаграма (на прикладі)

Дотримуймося прикладу піци. Підсумовуючи, у нас є клас піци, кухар та бетонні будівельники, які успадковуються від абстрактного будівельника. Ми пояснимо діаграму знизу вгору:

  • Pizza_Product: Цей клас - фактична піца. Він представлений трьома ознаками: (1) Тісто, (2) соус і (3) начинка.
  • ConcreteBuilder: Кожен конкретний будівельник відповідає за конкретне представлення. У цьому прикладі ми маємо Маргариту та Пікантну піцу. Обидва конкретні будівельники зобов'язані "побудувати" своє представлення піци на основі трьох перелічених вище атрибутів.
  • AbstractBuilder: Містить змінну члена піци, і конкретні будівельники успадковують її.
  • Cook_Director: У цьому прикладі режисер є фактичним кухарем. Клас несе відповідальність за ініціювання побудови заданого зображення, склавши шматки так, щоб будівельник дотримувався та адаптувався відповідно до потреб директора.

Крок 3 - Код за прикладом

Я б запропонував скопіювати клас коду за класом з мого сховища git "Andreas Poyias" або фрагментів нижче (у наданому порядку) та вставити його в будь-який із доступних онлайн-редакторів C ++, як c ++ shell, jdoodle, onlineGDBand запустити його спостерігати за результатами. Потім прочитайте коментарі чи опис нижче. Знайдіть час, щоб прочитати його ретельно (це означає одну хвилину, не менше і не більше).

Товар:
Це клас піци. Це простий клас з трьома сеттерами та методом смаку (), який друкує всі інгредієнти.

#include 
#include <пам'ять> // unique_ptr
використання простору імен std;
клас Pizza_Product
{
загальнодоступний:
 void setDough (рядок const & тісто) {m_dough = тісто; }
 void setSauce (const string & соус) {m_sauce = соус; }
 пустота setTopping (рядок const & топінг) {m_topping = топінг; }
void taste () const
{
  cout << "Піца з" << m_dough << "тісто",
       << m_sauce << "соус і"
       << m_topping << "Топінг. Мммммммм." << endl;
}
приватний:
 рядок m_dough;
 рядок m_sauce;
 рядок m_topping;
};

Анотація Builder:
Абстракціоніст - це інтерфейс, який містить об’єкт піци. У ньому є геттер, який повертає об'єкт піци та метод інстанцізації об'єкта піци. Він також оголошує три методи будівельника, які будуть впроваджені конкретизаторами далі.

клас Pizza_Builder
{
загальнодоступний:
  віртуальний ~ Pizza_Builder () {};
  Pizza_Product * getPizza () {return m_pizza.release (); }
  недійсне створенняNewPizzaProduct ()
  {
    m_pizza = make_unique  ();
  }
  virtual void buildDough () = 0;
  virtual void buildSauce () = 0;
  virtual void buildTop () = 0;
захищено:
  unique_ptr  m_pizza;
};

Бетонні будівельники:
Два приклади бетонних будівельників та два представлення піци. Вони обидва реалізують свої власні методи побудови, використовуючи об'єкт m_pizza з батьківського класу (Анотаційний конструктор)

клас Margherita_ConcreteBuilder: громадська Pizza_Builder
{
загальнодоступний:
 virtual void buildDough () {m_pizza-> setDough ("крос"); }
 virtual void buildSauce () {m_pizza-> setSauce ("помідор"); }
 virtual void buildTop () {m_pizza-> setTopping ("моцарела + базилік"); }
};
клас Spicy_ConcreteBuilder: громадська Pizza_Builder
{
загальнодоступний:
 virtual void buildDough () {m_pizza-> setDough ("каструля запечена"); }
 virtual void buildSauce () {m_pizza-> setSauce ("помідор + чилі"); }
 virtual void buildTop () {m_pizza-> setTopping ("пепероні + салямі"); }
};

Директор:
Цей клас поєднує все разом. Він має змінну Pizza_Builder. Він використовує makePizza () для отримання конкретного будівельника як параметр. Потім викликає операції збирання, які працюють для обох представлень відповідно. Тому ми досягаємо мети створити один конструктивний код для представлення різних типів піц. Метод tastePizza () - це надрукувати вміст піци.

клас Cook_Director
{
загальнодоступний:
 void tastePizza () {m_pizzaBuilder-> getPizza () -> смак (); }
пустота makePizza (Pizza_Builder * pb)
 {
   m_pizzaBuilder = pb;
   m_pizzaBuilder-> createNewPizzaProduct ();
   m_pizzaBuilder-> buildDough ();
   m_pizzaBuilder-> buildSauce ();
   m_pizzaBuilder-> buildTop ();
 }
приватний:
 Pizza_Builder * m_pizzaBuilder;
};

Головна (клієнт):
 Основний метод функціонує як клієнт (такий же, як і попередні посібники). Клієнт так легко може скласти різні уявлення про піцу. Нам потрібен директор, і тоді, просто передавши два різних конкретних будівельників як параметр themakePizza, ми зможемодокуштувати два різних типи піц.

int main ()
{
  Cook_Director Cook;
  Margherita_ConcreteBuilder margheritaBuilder;
  Spicy_ConcreteBuilder spicyPizzaBuilder;
  cook.makePizza (& margheritaBuilder);
  cook.tastePizza ();
  cook.makePizza (& spicyPizzaBuilder);
  cook.tastePizza ();
}
// Вихід
// Піца з перехресним тістом, томатним соусом і моцарелою + начинка з базиліка. // Ммммммм.
// Піца з запеченим на сковороді тістом, помідором + соусом чилі і
// перець + салатний начинка. Ммммммм.

Підсумовуємо переваги цієї моделі:

  • Існує багато можливих уявлень, але лише одне загальне введення.
  • У нас є стандартний протокол для створення всіх можливих уявлень. Етапи цього протоколу чітко піддаються інтерфейсу Builder.
  • Для кожного цільового подання існує один похідний конкретний клас.
  • Розробнику легко додати нове самостійне та незалежне представлення (Pizza), не побоюючись зламати щось інше.
  • Клієнт може просто зареєструвати ConcreteBuilder у директора та отримати очікуване представлення.

Наступний блог стане коротким посібником щодо дизайну дизайну Decorator. Це структурний зразок, необхідний для вашого сховища знань. Не забудьте сподобатися / заплескати мій пост у блозі та слідкуйте за моїм обліковим записом. Це дає мені задоволення, що я допоміг деяким колегам-розробникам і змусив мене продовжувати писати. Якщо є конкретна модель дизайну, про яку ви хотіли б дізнатися, то повідомте мені про це в коментарях нижче, щоб я міг надати її вам протягом наступних кількох тижнів.

Інші швидкі посібники щодо моделей дизайну:

  1. Шаблони дизайну - Швидкий посібник по абстрактній фабриці.
  2. Шаблони дизайну - Швидкий посібник із мостового шаблону.
  3. Шаблони дизайну - Швидкий посібник щодо шаблону для будівельників.
  4. Шаблони дизайну - Швидкий посібник з візерунком декораторів.
  5. Шаблони дизайну - Швидкий посібник з фасадної схеми.
  6. Шаблони дизайну - Швидкий посібник із шаблону спостерігачів.
  7. Шаблони дизайну - Швидкий посібник по Singleton Pattern.