История моей кофейни:

есть хорошо известная кофейня под названием GalaxyBucks с традиционным меню, но в последний период маркетолог обнаружил, что количество людей, посещающих кофейню, уменьшилось.
Поэтому он решил решить эту проблему и добавить в меню множество разновидностей, таких как молоко, мокко, шоколад, соя и т. д.

текущая реализация:

он открыл текущую реализацию меню и нашел эту реализацию:

Кофе: это абстрактный класс.
В меню 4 вида кофе: американо, эспрессо, капучино, deCaf.

Поэтому он добавил все новые опции в качестве подкласса в Coffee SuperClass. Результат:

после того, как он закончил реализацию, он почувствовал, что что-то не так

проблемы в этой реализации:

  • это переполненная конденсаторная реализация.
  • если вы хотите добавить новую категорию или новый тип кофе, вы создадите его собственный класс и внедрите его.
  • что будет, если цена на молоко изменится ?! вы измените весь метод затрат во всех классах кофе. (открыт для модификации)

Давайте посмотрим, как шаблон проектирования решит эти проблемы:

Сначала мы должны быть знакомы с очень важным принципом проектирования в программном обеспечении, это второй принцип SOLID для Дядя Боб

Принцип открытия / закрытия: классы должны быть открыты для расширения, но закрыты для модификации.

Во-вторых, мы определим шаблон "Декоратор", он взят из шаблона проектирования структуры.

Шаблон дизайна "Декоратор". Добавляйте дополнительные обязанности к объекту динамически. Декораторы предоставляют гибкую альтернативу созданию подклассов для расширения функциональности.

Это означает, что вы можете прикрепить к своему объекту определенную функцию или дополнительное поведение. Давайте применим это в нашей кофейне
UseCase: мы хотим рассчитать стоимость чашка кофе американо с двойным мокко, молоком и шоколадом.

Как мы это сделаем?
- возьмите подкласс кофе Американо.
- украсьте его мокко, а затем снова украсьте мокко.
- украсьте молоком а затем украсьте его шоколадом.
- вызовите cost () этого компонента, чтобы вычислить его с добавлением стоимости других элементов декора.

Основная реализация этого шаблона проектирования:

Реализация нашей кофейни:

- компонент может использоваться каждым сам по себе или быть обернутым украшением.
- ConcreteComponent: это подкласс, который может быть украшен любым элементом декорации.
- Decorator реализует тот же интерфейс или абстрактный класс в качестве компонента, который он собирается украсить.
- каждый декоратор HAS-A (обертывает) компонент, что означает, что декоратор содержит ссылочную переменную компонента, который собирается его украсить.
- примечание: мы используем wrappedObject: coffee в каждом подклассе декоратора только для упрощения реализации в приведенном ниже коде.

Теперь обратите внимание на реализацию метода затрат в каждом классе в нашем сценарии использования «Чашка кофе по-американски с двойным мокко, мягкий и шоколадный».

Для американского кофе:

Примечание: кофе - это абстрактный класс с абстрактным методом float Cost ();

Для реализации Mocha, Milk and Chocolate Decorator:

Примечание. CoffeeDecorator - это абстрактный класс, расширяющий абстрактный класс Coffee.
Примечание: если абстрактный класс расширяет другой абстрактный класс, можно перезаписать абстрактные методы родительского класса. Класс, но во всех случаях ошибки компиляции не будет.

Примечание: мы выполнили принципы SOLID в этой реализации:
1 - мы не изменяли родительский класс coffee.
2 - просто добавить новый декоратор, например ( soy) или добавить новый тип кофе, расширив родительские классы и не изменяя их, чтобы он был открыт для расширения, но закрыт для модификации.

Теперь наша основная реализация для нашего варианта использования:

Итак, теперь вы получите этот чек 0.o:
«ваш чек на кофе американо с двойным мокко, молоком и шоколадом составляет 2,0 доллара».

Наслаждайтесь и Приятного аппетита;)

Ссылки:
SourceMaker & head first design pattern.