Декоратор (англ. Decorator) относиться к классу структурных шаблонов. Он используется для динамического расширения
функциональности объекта. Является гибкой альтернативой наследованию.
Смысл заключается в том, чтобы можно было безболезненно комбинировать различные декораторы в произвольном порядке,
навешивая их на различные объекты. В некотором роде, это похоже на технологию traits, за исключением того,
что декораторы динамически навешиваются на объект, а traits статически на класс.
На примере мы имеем класс Cheeseburger, который реализует интерфейс BurgerInterface.
Тут мы замечаем, что в классе Cheeseburger не хватает сыра. Это основной ингредиент чизбургера и хорошо бы нам дописать
его в класс. Но давайте представим, что переписывать класс мы не можем. “Давайте наследуем Cheeseburger и расширим его”, скажете вы.
А если нам нужно ещё что-то добавить к Cheeseburger? Опять наследование.
А если нужно это всё объединить и ещё что-то добавить? Опять наследование. Потом опять и опять…
Декоратор помогает нам сделать это всё более гибко.
Так как наш абстрактный декоратор AbstractDecorator реализует интерфейс BurgerInterface,
мы можем расширять его на уровне абстракции.
Добавим сыр средствами CheeseburgerCheeseDecorator.
Наш декоратор (наследник AbstractDecorator), в конструктор ждёт объект типа BurgerInterface.
Как упоминалось выше, AbstractDecorator реализует интерфейс BurgerInterface. Но метод BurgerInterface->makeBurger()
он не реализует, а помечает как абстрактный. Это значит что наследники должны реализовать его.
Вот в нём мы будем декорировать наш чизбургер.
А теперь давайте поменяем соус в чизбургере.
Создаем новый декоратор CheeseburgerSauceDecorator (наследник AbstractDecorator).
Теперь мы можем расширять любой объект типа BurgerInterface.
Это может быть как исходный чизбургер без сыра(объект Cheeseburger->makeBurger()), так и уже декорированный с сыром (CheeseburgerCheeseDecorator->makeBurger()).