Evgenii Legotckoi
Қыр. 26, 2018, 4:01 Т.Қ.

Құрылымдық дизайн үлгілері - Декоратор

Цели

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

Проблематика

Вы хотите добавить поведение или состояние к отдельным объектам во время выполнения. Наследование не представляется возможным, поскольку оно является статичным и относится ко всему классу.


Обсуждение

Предположим, вы работаете с инструментарием пользовательского интерфейса, и вы хотите поддерживать добавление границ и полос прокрутки в окна. Вы можете определить иерархию наследования, например ...

Но шаблон Decorator предлагает дать клиенту возможность указать любую комбинацию «функций».

Widget* aWidget = new BorderDecorator(
  new HorizontalScrollBarDecorator(
    new VerticalScrollBarDecorator(
      new Window( 80, 24 ))));
aWidget->draw();

Эта гибкость может быть достигнута при следующем дизайне

Другой пример использования каскадных (или цепочечных) функций для создания пользовательского объекта может выглядеть так.

Stream* aStream = new CompressingStream(
  new ASCII7Stream(
    new FileStream("fileName.dat")));
aStream->putString( "Hello world" );

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

Обратите внимание: этот шаблон позволяет добавлять функционал к объекту, а не к интерфейсу объекта. Интерфейс, представленный клиенту, должен оставаться постоянным, поскольку указываются последовательные слои.

Также обратите внимание, что идентификация основного объекта теперь «скрыта» внутри объекта декоратора. Попытка прямого доступа к основному объекту теперь является проблемой.

Структура

Клиент всегда заинтересован в методе CoreFunctionality.doThis() . Клиент может или не может быть заинтересован в OptionalOne.doThis() и OptionalTwo.doThis(). Каждый из этих классов всегда делегирует обязанности к базовому классу Decorator, и этот класс всегда делегирует обязанности объекте обёртке.

Пример

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

Другой пример: штурмовой пистолет - это смертельное оружие. Но вы можете применить определенные «украшения», чтобы сделать его более точным, тихим и разрушительным.

Контрольный список

  1. Убедитесь, что контекст имеется: одна из основных (или необязательных) компонент, несколько дополнительных украшений или оберток и интерфейс, общий для всех.
  2. Создайте интерфейс самого низкого уровня (LCD класс), который делает все классы взаимозаменяемыми.
  3. Создайте базовый класс второго уровня (Decorator) для поддержки необязательных классов-оболочек.
  4. Класс Core и класс Decorator наследуются от интерфейса LCD.
  5. Класс Decorator объявляет композиционное отношение к интерфейсу LCD, и этот элемент данных инициализируется в его конструкторе.
  6. Класс Decorator делегирует объект LCD.
  7. Определите производный класс Decorator для каждого дополнительного приукрашивания.
  8. Производные классы Decorator реализуют свою функциональность оболочки - и - делегируют базовый класс Decorator.
  9. Клиент настраивает тип и порядок объектов Core и Decorator.

Эмпирические правила

  • Адаптер предоставляет другой интерфейс для своего объекта. Прокси обеспечивает тот же интерфейс. Декоратор обеспечивает расширенный интерфейс.
  • Адаптер изменяет интерфейс объекта, Decorator расширяет функционал объекта. Декоратор, таким образом, более прозрачен для клиента. Как следствие, Decorator поддерживает рекурсивную композицию, что невозможно при использовании чистых адаптеров.
  • Компоновщик и декоратор имеют аналогичные структурные диаграммы, отражающие тот факт, что оба полагаются на рекурсивную композицию для организации открытого числа объектов.
  • Декоратор можно рассматривать как вырожденный компоновщик с одним компонентом. Однако Decorator добавляет дополнительный функционал - он не предназначен для агрегации объектов.
  • Decorator предназначен для добавления функционала к объектам без подкласса. Цель компоновщика - это не украшение, а представление. Эти намерения отличаются друг от друга, но дополняют друг друга. Следовательно, компоновщик и декоратор часто используются совместно.
  • Composite может использовать Chain of Responsibility, чтобы позволить компонентам получать доступ к глобальным свойствам через своего родителя. Он также может использовать Decorator для переопределения этих свойств по частям композиции.
  • Декоратор и прокси имеют разные цели, но аналогичные структуры. Оба описывают, как обеспечить уровень аьстракции к другому объекту, а реализации содержат ссылку на объект, к которому они направляют запросы.
  • Декоратор позволяет вам изменять представление объекта.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз