Структурные шаблоны / Декоратор
Обертка
(Wrapper
)
Вы разработали систему оповещений, которая может отслеживать различные события и отсылать пользователю сообщение по электронной почте.
Потом вы добавили в нее возможность слать сообщения в facebook, реализовав их как отдельный подкласс. Теперь ваша программа при инициализации выбирает нужную Стратегию (Strategy) и использует ее.
Но вдруг пользователи захотели, чтобы была возможность слать оповещения и на почту и в facebook одновременно. Если у вас всего два подкласаа - никаких проблем, можно создать дополнительно их комбинацию. А если таких стратегий десять?
Лучше, чтобы была возможность добавлять нужные опции при необходимости - или не добавлять вообще.
Позволяет добавить объекту дополнительное поведение, не изменяя его код.
Является удобной и гибкой альтернативой субклассированию.
Декоратор обычно ДОПОЛНЯЕТ поведение оборачиваемого компонента, а НЕ ЗАМЕНЯЕТ его.
Декораторов может быть много - один поверх другого. Это просто, так как задекорированный объект выглядит точно так же как незадекорированный.
Component
- общий интерфейс для компонентов и декораторов.ConcreteComponent
- класс компонентаDecorator
,ConcreteDecoratorA
,ConcreteDecoratorB
Декоратор реализует тот же интерфейс, что и компонент, который он оборачивает (может являться сестринским классом для этого компонента - субклассировать тот же абстрактный класс). Таким образом, другой объект не видит разницы между исходным компонентом и компонентом в обертке.
Декоратор получает компонент, который нужно обернуть, выполняет свои дополнительные действия и вызвает нужный метод самого компонента (последовательность этих операций может быть любой - до, после, до и после вызова самого компонента).
Обычно и сам компонент, и все декораторы наследуют от одного класса, так как у них должен быть одинаковый интерфейс.
- Кофе с добавками
- Матрешка
- Одежда
- Необходимо добавить какому-то объекту функциональности, но нельзя по каким-либо причинам изменять его код.
- Гораздо более гибкий механизм, чем наследование.
- Можно изменять функционал на лету.
- Много маленьких классов.
- Трудно конфигурировать многократно обернутые объекты.
Шаблон Декоратор
дополняет интерфейс исходного объекта.
- Адаптер (Adapter) - меняет интерфейс исходного объекта.
- Заместитель (Proxy) - сохраняет интерфейс исходного объекта.
- Компоновщик (Composite). Также использует рекурсивную вложенность для связи большого количества объектов в одну структуру.
- Цепочка обязанностей (Chain of Responsibility). Также построена на рекурсивном выполнении операций.
Способы реализации паттерна (вариации механизмов работы паттерна)
- Прототип (Prototype). Позволяет клонировать сложные структуры компоновщика.