Візерунок дизайну декораторів на зразок вафлі

Шаблон декоратора - це додавання додаткових функцій до існуючого об'єкта.

Це звучить як французький?

Не хвилюйтесь.

Ми повернемося до цього пізніше.

Давайте спочатку подивимося на деякі вафлі!

Геніальна частина вафлі полягає в тому, що вони починаються просто і просто. Оскільки вони прості, з ними майже все на смак

Деякі поширені начинки для вафель - це полуниця, чорниця, ожина, банани, мигдаль та сиропи.

Спробуємо створити колекцію різних вафельних предметів.

Будуть StrawberryWaffle, BlueberryWaffle, BlackberryWaffle, BananaWaffle, AlmondWaffle та SyrupWaffle.

Зачекайте, ми можемо полуницю та чорницю на одній вафлі. Це дає нам StrawberryBlueberryWaffle.

На одній вафлі ми можемо також полуницю та ожину. Це дає нам StrawberryBlackberryWaffle.

Ніхто не забороняє нам класти три начинки на одну і ту ж вафлю. Це дає нам StrawberryBlueberryBlackberryWaffle.

Щоб зробити все просто, розглянемо полуницю, чорницю та ожину як потенційні начинки. Існує вісім різних комбінацій [1].

Чи означає це, що нам потрібно створити вісім різних об’єктів для нашої колекції вафель?

Якщо ми додамо банани до нашого потенційного списку начинок, є 16 різних комбінацій [2].

Очевидно, що додавання єдиного відливу до нашого списку начинок викликає вибух у нашій колекції вафель.

Неможливо створити інший клас вафель для кожної можливої ​​комбінації начинок. Має бути кращий спосіб зробити це.

Що робити, якщо ми хочемо StrawberryWaffle замість створення StrawberryWaffle, ми створимо вафлі та додамо до неї полуницю?

Що з StrawberryBlueberryWaffle тоді?

Ми можемо створити вафлі, додати до неї полуницю та додати чорницю!

Створення вафельних класів

Давайте подивимось на клас простої вафлі:

Ви можете створити вафлю, подавати її і їсти так:

А ось клас StrawberryWaffle:

Зауважте, ми передаємо вафельний предмет всередині конструктора StrawberryWaffle, щоб створити StrawberryWaffle.

Клас StrawberryWaffle має:

  1. Вафлі, що передаються
  2. Полуниця як топінг
  3. Спосіб обслуговування, який викликає метод подачі вафлі, що передається. Потім відбитки, увінчані полуницею
  4. Спосіб їжі, який називає метод їжі, що передається вафлею, а потім друкує, а потім їсть трохи полуниці

Ви можете створити вафлі з полуниці, подавати її і їсти так:

Ось класи BlueberryWaffle та BlackberryWaffle:

І ви можете використовувати їх так:

Витягнення загальної частини

Помітивши клас StrawberryWaffle, клас BlueberryWaffle і клас BlackberryWaffle майже ідентичні, за винятком їх доливання, ми можемо витягнути спільні частини як батьківський клас.

У WaffleDecorator добування більше не є атрибутом об'єкта. Натомість це метод, який може бути замінений дочірнім класом.

Тепер ми можемо переписати StrawberryWaffle, BlueberryWaffle та BlackberryWaffle, щоб успадкувати WaffleDecorator, щоб отримати ці загальні функції:

І вони повинні працювати так само, як і раніше:

Ось класи, які ми створюємо:

Створення вафлі BlueberryStrawberry

Зараз у нас є вафлі, полуничні вафлі, чорничні вафлі та BlackberryWaffle.

Настав час досягти мети, яку ми спочатку поставили:

створіть вафлю, додайте до неї полуницю і додайте до неї чорницю.

Просто так:

І ми можемо:

Що відбувається?!

Давайте докладніше розглянемо, як ми створили blueberry_strawberry_waffle:

По-перше, ми створили звичайний_ вафле з Waffle: plain_waffle = Waffle.new

Потім ми створили strawberry_waffle, передавши звичайний_waffle в конструктор StrawberryWaffle. strawberry_waffle = StrawberryWaffle.new (plain_waffle)

Варто зазначити, що коли ми створюємо strawberry_waffle, ми зберігаємо пропущений звичайний_waffle як змінну екземпляра strawberry_waffle:

Як ми бачимо, strawberry_waffle.waffle та plain_waffle - це той самий об’єкт:

У цей момент, коли ми називаємо strawberry_waffle.serve. Ми спочатку закликаємо plain_waffle.serve, після чого друкуємо з полуницею.

Для strawberry_waffle.eat ми спочатку називаємо plain_waffle.eat, потім друкуємо, а потім їмо трохи полуниці.

Ми створюємо blueberry_strawberry_waffle, передаючи конструктор strawberry_waffleinto конструктору BlueberryWaffle. blueberry_strawberry_waffle = BlueberryStrawberryWaffle.new (strawberry_waffle)

Коли ми створюємо blueberry_strawberry_waffle, ми зберігаємо переданий strawberry_waffle як змінну екземпляра blueberry_strawberry_waffle:

Коли ми називаємо blueberry_strawberry_waffle.serve, ми спочатку називаємо strawberry_waffle.serve. Котрий називає plain_waffle.serve, тоді друкується на вершині полуниці. Потім друкуйте зверху чорницею.

Коли ми називаємо blueberry_strawberry_waffle.eat, ми спочатку називаємо strawberry_waffle.eat. Що називає plain_waffle.eat, потім друкує, а потім їсть трохи полуниці. Потім роздрукуйте, а потім з’їжте трохи чорниці.

Ключ магії:

strawberry_waffle побудований на вершині plain_waffle. А blueberry_strawberry_waffle побудований поверх полуниці_waffle.

Ключ у можливості будувати вафлі один на одного - всі вафлі повинні підкорятися одному інтерфейсу.

Всі вафлі мають метод подачі та їжу.

Ось чому в рамках StrawberryWaffle / BlueberryWaffle / BlackberryWaffleclasses ми впевнені, що вафлі, що передаються, мають спосіб подачі та спосіб їжі.

І ми можемо використовувати метод подачі та метод їжі з переданої вафлі, коли визначаємо новий метод подачі та новий метод їжі.

WaffleDecorator не дбає про тип вафлі. Це може бути звичайна вафля, полуниця_ вафля або чужа-вафелька.

Важливо лише те, що WaffleDecorator бере вафлі та повертає розширені вафлі. Вафля, яку вона бере, і вафлі, яку вона повертає, підкоряються тому ж інтерфейсу.

Оскільки всі декоратори, які беруть і повертають вафлі, дотримуються одного інтерфейсу, результат декоратора може бути переданий іншому декоратору.

Просто так:

або це:

Тепер із вафлями, StrawberryWaffle, BlueberryWaffle та BlackberryWaffle ми можемо створити всі вісім різних вафлі.

Додавання банана до нашого списку топових простих, як:

Ви щойно навчилися шаблону декораторів!

Ось його визначення:

Декоратор динамічно покладає додаткові обов'язки на предмет.

Винос:

  1. Шаблон декоратора - це легке додавання додаткових функцій до існуючого об'єкта.
  2. Об'єкт, який підлягає декоруванню (той, який передається всім декораторам), і об’єкти, повернуті від декораторів, повинні відповідати одному інтерфейсу.

Дякуємо за прочитане! Сподіваюся, вам сподобається стаття.

Я публікую на sihui.io щотижня.

Підпишіться, щоб ви не пропустили наступну статтю із серії.

Наступного разу ми подивимось на…

[1] PlainWaffle, StrawberryWaffle, BlueberryWaffle, BlackberryWaffle, StrawberryBlueberryWaffle, полуницяBlackberryWaffle, BlueberryBlackberryWaffle та StrawberryBlueberryBlackberryWaffle.

[2] C (4, 0) + C (4, 1) + C (4, 2) + C (4, 3) + C (4, 4) = 16