Шаблони дизайну - Швидкий посібник з малюнком декораторів.

Шаблон «Декоратор» - це структурний візерунок, який дозволяє динамічно додавати додаткові функції до об’єкта. Іншими словами, клієнт має свободу створити об'єкт, а потім розширити його, додавши до нього різноманітні "функції". Хорошою аналогією для спрощення цієї схеми є: "Згорнути подарунок, покласти його в коробку і загорнути в коробку".

Шаблон «Декоратор» класифікується серед структурних моделей дизайну, які стосуються складу класу та об’єкта. Структурні структури створення класів використовують спадкування для складання інтерфейсів. Структурні об'єкти-шаблони визначають способи складання об'єктів для отримання нової функціональності. [за шаблонами дизайну пояснено просто]

Рюкзак - ідеальний приклад візерунка «Декоратор»:

  • В наші дні рюкзаки можуть мати різноманітні функції. Особливості можуть варіюватися від простого, як слот для ноутбука, бічні кишені або навіть банк для живлення для зарядки через USB.
  • Основна мета шаблону декоратора - дозволити клієнту додавати всі необхідні функції, динамічно, безпечно та найпростішим способом. Він повинен бути таким же прямим вперед і охайним, як облягаючий рюкзак на малюнку.
  • Фрагмент коду нижче написаний навмисно, оскільки він так гарно сходиться з цитатою, про яку ми згадали вище: "Згорнути подарунок, скласти його в коробку і загорнути в коробку". Ми збираємо рюкзак, до якого ми додаємо USB зарядний пристрій, до якого додаємо слот для ноутбука, до якого ми додаємо…
int main // клієнт
{
  IBackpack * bp = новий LaptopSlot (новий UsbCharge (...))));
  повернути 1;
}

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

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

  • Гнучкість. Ми хочемо надати клієнту силу та гнучкість для динамічного додавання будь-якої функції до компонента / об'єкта, що може вважатися цінним.
  • Розширення функціональності: Назва може бути дещо введеною в оману, ця модель не лише стосується "прикраси" певного об'єкта, але в основному стосується розширення його функціональності.

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

Почнемо пояснювати схему знизу вгору. Мета - «зібрати» рюкзак і додати до нього кілька функціональних можливостей.

  • Бетонні декоратори: У нас є три приклади цих класів, які відповідають за розширення функціональності кожного: (1) LaptopSlot, (2) USBCharge, (3) WaterBottle. Вони містять реалізацію функціоналу і можуть відповідно "скласти" рюкзак. Зауважте, що у них є конструктор, який отримує декоратор як параметр.
  • Декоратор: Цей клас отримує вищевказані класи та успадковує компонент, який є IBackpack. У декоратора також є екземпляр IBackpack. Після екземпляра IBackpackis він використовується всередині методу збирання ().
  • Конкретний компонент: Цей клас є найважливішим фрагментом головоломки, оскільки він є ключем до з'єднання всього разом. Саме компонент (рюкзак) знаходиться в найтоншій формі, яку він міг отримати. Наприклад, звичайний рюкзак складається лише з «ремінців і головного відсіку». Простий рюкзак виконує роль старту ланцюга. Він передається конструктору декораторів і сам передається конструктору конкретного декоратора (для додання специфічних функцій, тобто слота для ноутбука), який може бути переданий іншому конструктору конкретного декоратора та іншому тощо.
  • Компонент: Це абстрактний вигляд предмета, який ми хочемо прикрасити. У нас можуть бути успадковані різні конкретні компоненти. У цьому прикладі ми можемо відокремлювати "PlainBackpack" як "OfficeBackpack", "CampingBackpack", "HikingBackpack", але ми вирішимо зробити його простим.

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

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

IBackpack:
Наступний фрагмент коду - це проста спадщина, IBackpackis, успадкована PlainBackpackclass. Усі похідні класи повинні реалізувати збирання (), оскільки це чиста віртуальна функція = 0 ;. У звичайному рюкзаку є тільки ремінці та основне відділення.

#include 
використання простору імен std;

клас IBackpack
{
загальнодоступний:
  віртуальна пустота збирання () = 0;
  віртуальний ~ IBackpack () {}
};

клас PlainBackpack: громадський IBackpack
{
загальнодоступний:
  віртуальна void assemble () {cout << "\ n ShoulderStraps and mainCompartment";}
};

BackpackDecorator:
Вищеописаний фрагмент відповідає за побудову простого рюкзака. Тепер прикрасимо його за допомогою BackpackDecorator. Декоратор успадковує від theIBackpack, що означає, що він повинен реалізувати метод theassemble (). Він також містить IBackpackobject, який використовується для делегування реалізації методу збирання () залежно від типу m_decorator.

Клас BackpackDecorator: громадський IBackpack
{
загальнодоступний:
  BackpackDecorator (IBackpack * decorator): m_Decorator (декоратор) {}
  
  збір віртуальної пустоти ()
  {
    m_Decorator-> збирати ();
  }
приватний:
  IBackpack * m_Decorator;
};

Бетонні декоратори:
У фрагменті нижче показані три різні декоратори, що походять від класуBackpackDecorator, який сам успадковує відBackpack. У цьому прикладі всі вони однакові за винятком реалізації асамблеї (). Перший додає ноутбукSlot, другий додає UBCharge, а третій додає waterBottle.

клас WithLaptopSlot: громадський BackpackDecorator
{
загальнодоступний:
  WithLaptopSlot (IBackpack * dcrator): BackpackDecorator (dcrator) {}
  збір віртуальної пустоти ()
  {
    BackpackDecorator :: збирати ();
    cout << "+ LaptopSlot";
  }
};
 
клас WithUSBCharge: громадський BackpackDecorator
{
загальнодоступний:
    WithUSBCharge (IBackpack * dcrator): BackpackDecorator (dcrator) {}
    збір віртуальної пустоти ()
    {
        BackpackDecorator :: збирати ();
        cout << "+ USBCharge";
    }
};
 
клас WithWaterBottle: громадський рюкзакDecorator
{
загальнодоступний:
    WithWaterBottle (IBackpack * dcrator): BackpackDecorator (dcrator) {}
    збір віртуальної пустоти ()
    {
        BackpackDecorator :: збирати ();
        cout << "+ WaterBottle";
    }
};

Головна (Клієнт):
Основний метод діє як клієнт (такий же, як і попередні посібники). Нарешті ми зможемо скласти всі частини головоломки разом. Але перш ніж це зробити, згадаймо, про що згадувалося в першому пункті блогу "Згорнути подарунок, скласти його в коробку і упакувати в коробку". Щоб зрозуміти це, ми повинні прочитати конструкцію рюкзака (у фрагменті нижче) у зворотному порядку:

  1. Створіть PlainBackpack.
  2. Передайте його в BackpackDecorator.
  3. Що передає його разом, щоб бути прикрашеним слотом для ноутбука.
  4. У свою чергу передається прикрасити заряд USB.
  5. Нарешті, «коробку» обмотують пляшкою з водою.

Також важливо дотримуватися порядку друку під час виклику збирання (). Порядок пов'язаний з тим, як ініціалізували конструктори. Знову починається з простого рюкзака і прикрашається до кінця, щоб дістатися до водяної пляшки.

int main ()
{
  IBackpack * pBackpack =
   новий WithWaterBottle (// 5
    новий WithUSBCharge (// 4
     новий WithLaptopSlot (// 3
      новий BackpackDecorator (// 2
       новий PlainBackpack ())))); // 1

  pBackpack-> збирати ();
  видалити pBackpack;

  повернути 0;
}
// Вихід
// Плечові пастки та mainCompartment + LaptopSlot + USBCharge
// + Водяна пляшка

Простота, запропонована клієнтові, є однією з найбільших переваг.

  • Клієнт має можливість динамічно збирати рюкзак з будь-якими доступними функціями.
  • Це просто, легко і безпечно.
  • Клієнту не потрібно змішуватися з кодом.
  • Додавання додаткового «похідного» декоратора є простим та незалежним від інших похідних декораторів.

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

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

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