Skip to content

Latest commit

 

History

History
84 lines (48 loc) · 9.35 KB

Decorator.md

File metadata and controls

84 lines (48 loc) · 9.35 KB

Декоратор

UML

Позволяет динамически добавлять объектам новую функциональность, оборачивая их в полезные «обёртки».

Декоратор имеет альтернативное название - «обёртка». Оно удачнее описывает суть паттерна: вы помещаете целевой объект в другой объект-обёртку, который запускает базовое поведение объекта, а затем добавляет к результату что-то своё.

  1. Декораторы имеют тот же супертип, что и декорируемые объекты;

  2. Объект можно завернуть в 1 или несколько декораторов;

  3. (из 1 следует) можно передать декорируемый объект вместо исходного;

  4. Декоратор добавляет свое действие до и/или после делегирования операций декорируемому объекту, выполняющему остальную роботу

  5. Объект может быть декорирован в любой момент времени, т.е. динамически и с произвольным кол. декораторов.

!!! Если программировать на уровне конкретного объекта Декоратор не подходит.

Применимость

  • Когда вам нужно добавлять обязанности объектам на лету, незаметно для кода, который их использует.

    • Объекты помещают в обёртки, имеющие дополнительные поведения. Обёртки и сами объекты имеют одинаковый интерфейс, поэтому клиентам без разницы с чем работать - с обычным объектом или обёрнутым.
  • Когда нельзя расширить обязанности объекта с помощью наследования.

    • Во многих языках программирования есть ключевое слово final, которое может заблокировать наследование класса. Расширить такие классы можно только с помощью Декоратора.

Шаги реализации

  1. Убедитесь, что в вашей задаче есть один основной компонент и несколько опциональных дополнений или надстроек над ним.

  2. Создайте интерфейс компонента, который описывал бы все общие методы как для основного компонента, так и для его дополнений.

  3. Создайте класс конкретного компонента и поместите в него основную бизнес-логику.

  4. Создайте базовый класс декораторов. Он должен иметь поле для хранения ссылки на вложенный объект-компонент. Все методы базового декоратора должны делегировать действие вложенному объекту.

  5. И конкретный компонент, и базовый декоратор должны следовать одному и тому же интерфейсу компонента.

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

  7. Клиент берёт на себя ответственность за конфигурацию и порядок обёртывания объектов.

Преимущества и недостатки

+ -
Большая гибкость, чем у наследования Трудно конфигурировать многократно обёрнутые объекты.
Позволяет добавлять обязанности на лету Обилие крошечных классов.
Можно добавлять несколько новых обязанностей сразу.
Позволяет иметь несколько мелких объектов вместо одного объекта на все случаи жизни.

Отношения с другими паттернами

  • Адаптер меняет интерфейс существующего объекта. Декоратор улучшает другой объект без изменения его интерфейса. Причём Декоратор поддерживает рекурсивную вложенность, чего не скажешь об Адаптере.

  • Адаптер предоставляет классу альтернативный интерфейс. Декоратор предоставляет расширенный интерфейс. Заместитель предоставляет тот же интерфейс.

  • Цепочка обязанностей и Декоратор имеют очень похожие структуры. Оба паттерна базируются на принципе рекурсивного выполнения операции через серию связанных объектов. Но есть и несколько важных отличий.

    Обработчики в Цепочке обязанностей могут выполнять произвольные действия, независимые друг от друга, а также в любой момент прерывать дальнейшую передачу по цепочке. С другой стороны Декораторы расширяют какое-то определённое действие, не ломая интерфейс базовой операции и не прерывая выполнение остальных декораторов.

  • Компоновщик и Декоратор имеют похожие структуры классов из-за того, что оба построены на рекурсивной вложенности. Она позволяет связать в одну структуру бесконечное количество объектов.

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

    Но они могут и сотрудничать: Компоновщик может использовать Декоратор, чтобы переопределить функции отдельных частей дерева компонентов.

  • Архитектура, построенная на Компоновщиках и Декораторах, часто может быть улучшена за счёт внедрения Прототипа. Он позволяет клонировать сложные структуры объектов, а не собирать их заново.

  • Стратегия меняет поведение объекта «изнутри», а Декоратор изменяет его «снаружи».

  • Декоратор и Заместитель имеют похожие структуры, но разные назначения. Они похожи тем, что оба построены на композиции и делегировании работы другому объекту. Паттерны отличаются тем, что Заместитель сам управляет жизнью сервисного объекта, а обёртывание Декораторов контролируется клиентом.