История моей кофейни:
есть хорошо известная кофейня под названием 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.