Реализация паттерна «Декоратор» в простом коде Java

Реализация паттерна "Декоратор" в простом коде JavaЕсли классы находятся на стадии проектирования, будет несложно добавить деко­раторы. Однако если необходимо снабдить декоратором существующую систему, вам может понадобиться переделать некоторые классы. Например, целевой класс должен реализовывать тот же интерфейс, что реализует декоратор.

Эта статья демонстрирует применение паттерна «Декоратор» при разработке упрощенной РОS-системы для пиццерии. В данной статье сможете прочитать где использовать паттерн декоратор. Каждая пицца может быть украшена дополнительными начинками, такими как двойной сыр и бесплатный чили.

Во-первых, вам предстоит создать интерфейс Order, реализуемый с помощью класса Pizza и абстрактного класса декоратора Extra. Класс Extra расширяется классами добавочных начинок: DoubleExtra, NoCostExtra и RegularExtra.

Начнем с создании интерфейса Order:

Далее создадим класс, представляющий в меню пиццу(«Четыре сезона», «Маргарита», «Гавайская» и т.д.). Это целевой объект для декорирования. Класс будет реализовать интерфейс Order.

Следующий код создает пиццу «Четыре сезона«.

Далее нам необходимо создать декораторы, которые будут «украшать» пиццу добавочными начинками. Используем абстрактный класс таким образом, чтобы конкретным классам не пришлось реализовать все бизнес-методы интерфейса. Абстрактный декоратор создаст шаблон, который смогут расширять другие деко­раторы.

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

Таким образом, вам нужен декоратор, не добавляющий ничего к цене пиццы, но обеспечивающий со­ответствующую маркировку ( что был заказан дополнительный чили ).

Кроме того,посетитель может попросить две дополнительные порции сыра и, если система напечатает «сыр» дважды, шеф-повар может подумать, что это ошибка в програм­ме, и добавить только одну порцию сыра.

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

Теперь, когда у вас есть абстрактный декоратор, вы можете добавлять конкретное поведение и создавать конкретные декораторы. Вы начнете с декоратора RegularExtra, добавляющего цену и этикетку к целевому объекту (пицце).

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

Далее нам нужно создать NoCostDecorator, который меняет строку label, но не добавляет ничего к цене пиццы. Следующий декоратор добавляет дополнительные начинки бесплатно.

Дальше создаем наш последний декоратор DoubleExtra, чтобы избежать двукратной печати начинки на этикетке. Он удваивает цену и добавляет ключевое слово double перед целевой этикеткой.

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

Вывод в консоли будет следующим:

Но погодите! Здесь есть потенциальная ошибка! Чили не бесплатен, если вы
заказываете его как гарнир, но шеф-повар с радостью подаст его бесплатно в пиц­це. Вам нужно позаботиться, чтобы система учитывала это различие. Только представьте себе, что эти значения и этикетки берутся из базы данных.

Что бы вы сделали для создания различных видов поведения для чили? Одним вариантом могло бы быть создание двух объектов для чили: один был бы маркирован как «с пиццей».

Конечно, это была бы халтура, оставляющая любому официанту лазей­ку для заказа бесплатного чили для его друзей. Другим вариантом стало бы соз­дание дополнительного конструктора в абстрактном классе, не принимающего цену в качестве параметра. Любой не взимающий плату за добавки декоратор мог бы реализовать это.