Позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки».
Декоратор имеет альтернативное название - «обёртка». Оно удачнее описывает суть паттерна: вы помещаете целевой объект в другой объект-обёртку, который запускает базовое поведение объекта, а затем добавляет к результату что-то своё.
-
Декораторы имеют тот же супертип, что и декорируемые объекты;
-
Объект можно завернуть в 1 или несколько декораторов;
-
(из 1 следует) можно передать декорируемый объект вместо исходного;
-
Декоратор добавляет свое действие до и/или после делегирования операций декорируемому объекту, выполняющему остальную роботу
-
Объект может быть декорирован в любой момент времени, т.е. динамически и с произвольным кол. декораторов.
!!! Если программировать на уровне конкретного объекта Декоратор не подходит.
-
Когда вам нужно добавлять обязанности объектам на лету, незаметно для кода, который их использует.
- Объекты помещают в обёртки, имеющие дополнительные поведения. Обёртки и сами объекты имеют одинаковый интерфейс, поэтому клиентам без разницы с чем работать - с обычным объектом или обёрнутым.
-
Когда нельзя расширить обязанности объекта с помощью наследования.
- Во многих языках программирования есть ключевое слово
final
, которое может заблокировать наследование класса. Расширить такие классы можно только с помощью Декоратора.
- Во многих языках программирования есть ключевое слово
-
Убедитесь, что в вашей задаче есть один основной компонент и несколько опциональных дополнений или надстроек над ним.
-
Создайте интерфейс компонента, который описывал бы все общие методы как для основного компонента, так и для его дополнений.
-
Создайте класс конкретного компонента и поместите в него основную бизнес-логику.
-
Создайте базовый класс декораторов. Он должен иметь поле для хранения ссылки на вложенный объект-компонент. Все методы базового декоратора должны делегировать действие вложенному объекту.
-
И конкретный компонент, и базовый декоратор должны следовать одному и тому же интерфейсу компонента.
-
Теперь создайте классы конкретных декораторов, наследуя их от базового декоратора. Конкретный декоратор должен выполнять свою добавочную функциональность, а затем (или перед этим) вызывать эту же операцию обёрнутого объекта.
-
Клиент берёт на себя ответственность за конфигурацию и порядок обёртывания объектов.
+ | - |
---|---|
Большая гибкость, чем у наследования | Трудно конфигурировать многократно обёрнутые объекты. |
Позволяет добавлять обязанности на лету | Обилие крошечных классов. |
Можно добавлять несколько новых обязанностей сразу. | |
Позволяет иметь несколько мелких объектов вместо одного объекта на все случаи жизни. |
-
Адаптер меняет интерфейс существующего объекта. Декоратор улучшает другой объект без изменения его интерфейса. Причём Декоратор поддерживает рекурсивную вложенность, чего не скажешь об Адаптере.
-
Адаптер предоставляет классу альтернативный интерфейс. Декоратор предоставляет расширенный интерфейс. Заместитель предоставляет тот же интерфейс.
-
Цепочка обязанностей и Декоратор имеют очень похожие структуры. Оба паттерна базируются на принципе рекурсивного выполнения операции через серию связанных объектов. Но есть и несколько важных отличий.
Обработчики в Цепочке обязанностей могут выполнять произвольные действия, независимые друг от друга, а также в любой момент прерывать дальнейшую передачу по цепочке. С другой стороны Декораторы расширяют какое-то определённое действие, не ломая интерфейс базовой операции и не прерывая выполнение остальных декораторов.
-
Компоновщик и Декоратор имеют похожие структуры классов из-за того, что оба построены на рекурсивной вложенности. Она позволяет связать в одну структуру бесконечное количество объектов.
Декоратор оборачивает только один объект, а узел Компоновщика может иметь много детей. Декоратор добавляет вложенному объекту новую функциональность, а Компоновщик не добавляет ничего нового, но «суммирует» результаты всех своих детей.
Но они могут и сотрудничать: Компоновщик может использовать Декоратор, чтобы переопределить функции отдельных частей дерева компонентов.
-
Архитектура, построенная на Компоновщиках и Декораторах, часто может быть улучшена за счёт внедрения Прототипа. Он позволяет клонировать сложные структуры объектов, а не собирать их заново.
-
Стратегия меняет поведение объекта «изнутри», а Декоратор изменяет его «снаружи».
-
Декоратор и Заместитель имеют похожие структуры, но разные назначения. Они похожи тем, что оба построены на композиции и делегировании работы другому объекту. Паттерны отличаются тем, что Заместитель сам управляет жизнью сервисного объекта, а обёртывание Декораторов контролируется клиентом.