Декоратор

Шаблон оформления декоратора

Намерение

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

Проблема

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

Обсуждение

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

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

Виджет *  aWidget  =  new  BorderDecorator ( новый HorizontalScrollBarDecorator ( новый VerticalScrollBarDecorator ( новое окно ( 80 , 24 ) ) ) ) ; aWidget -> draw ( ) ;
   
     
          

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

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

Stream *  aStream  =  новый  CompressingStream ( новый ASCII7Stream ( новый FileStream ( "fileName.dat" ) ) ) ; aStream -> putString ( "Привет, мир" ) ;
   
     
  

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

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

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

Состав

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

пример

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

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

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

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

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

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

Design pattern

Design pattern

В программной инженерии шаблон проектирования – это общее повторяемое решение часто встречающейся проблемы при разработке программного обеспечения. Шаблон проектирования – это не законченный дизайн, который можно преобразовать непосредственно в код. Это описание или шаблон решения проблемы, который можно использовать во многих различных ситуациях.

Использование шаблонов дизайна

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

Часто люди понимают только, как применять определенные методы проектирования программного обеспечения к определенным проблемам. Эти методы трудно применить к более широкому кругу проблем. Шаблоны проектирования предоставляют общие решения, задокументированные в формате, который не требует специфики, привязанной к конкретной проблеме.

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

Шаблоны творческого проектирования

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

 
  • Абстрактная фабрика
    Создает экземпляр нескольких семейств классов
  • Builder
    Отделяет построение объекта от его представления
  • Заводской метод
    Создает экземпляр нескольких производных классов
  • Пул объектов
    Избегайте дорогостоящего приобретения и высвобождения ресурсов за счет утилизации объектов, которые больше не используются
  • Прототип
    Полностью инициализированный экземпляр для копирования или клонирования.
  • Синглтон
    Класс, из которого может существовать только один экземпляр

Структурные шаблоны проектирования

Эти шаблоны проектирования связаны с составом классов и объектов. Структурные шаблоны создания классов используют наследование для создания интерфейсов. Структурные шаблоны объектов определяют способы компоновки объектов для получения новых функциональных возможностей.

  • Адаптер
    Match интерфейсов разных классов
  • Мост
    отделяет интерфейс объекта от его реализации
  • Составной
    Древовидная структура простых и составных объектов.
  • Декоратор
    Динамическое добавление обязанностей к объектам
  • Фасад
    Единый класс, представляющий всю подсистему
  • Легковес
    Мелкозернистый экземпляр, используемый для эффективного обмена
  • Данные частного класса
    ограничивают доступ к средствам доступа / мутаторам
  • Прокси
    Объект, представляющий другой объект

Поведенческие шаблоны проектирования

Все эти шаблоны проектирования связаны с взаимодействием объектов Class. Поведенческие паттерны – это те паттерны, которые наиболее конкретно связаны с общением между объектами.

  • Цепочка ответственности
    Способ передачи запроса между цепочкой объектов
  • Команда
    Инкапсулирует запрос команды как объект
  • Интерпретатор
    Способ включения языковых элементов в программу
  • Итератор
    Последовательный доступ к элементам коллекции
  • Посредник
    Определяет упрощенное взаимодействие между классами
  • Memento
    Захват и восстановление внутреннего состояния объекта
  • Нулевой объект
    Предназначен для использования в качестве значения объекта по умолчанию
  • Наблюдатель
    Способ уведомления об изменении ряда классов
  • Состояние
    Изменение поведения объекта при изменении его состояния
  • Стратегия
    инкапсулирует алгоритм внутри класса
  • Шаблонный метод
    Отложите точные шаги алгоритма на подкласс
  • Посетитель
    Определяет новую операцию для класса без изменений

Критика

Концепция шаблонов проектирования подвергалась критике со стороны некоторых специалистов в области информатики.

Нацелен на неправильную проблему

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

Питер Норвиг приводит аналогичный аргумент. Он демонстрирует, что 16 из 23 шаблонов в книге Design Patterns (которая в основном ориентирована на C ++) упрощены или устранены (посредством прямой языковой поддержки) в Lisp или Dylan.

Отсутствие формальных основ

Изучение шаблонов проектирования было чрезмерно спонтанным, и некоторые утверждали, что эту концепцию срочно необходимо поставить на более формальную основу. На OOPSLA 1999 «Банда четырех» (при их полном сотрудничестве) предстала перед показательным судом, в ходе которого они были «обвинены» в многочисленных преступлениях против информатики. Они были «осуждены» ⅔ из «присяжных», присутствовавших на суде.

Приводит к неэффективным решениям

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

Существенно не отличается от других абстракций

Некоторые авторы утверждают, что шаблоны проектирования существенно не отличаются от других форм абстракции и что использование новой терминологии (заимствованной из архитектурного сообщества) для описания существующих явлений в области программирования не требуется. Парадигма модель-представление-контроллер рекламируется как пример «шаблона», который на несколько лет предшествует концепции «шаблонов проектирования». Некоторые также утверждают, что основным вкладом сообщества шаблонов проектирования (и книги «Банда четырех») было использование языка шаблонов Александра в качестве формы документации; практика, которая часто игнорируется в литературе.