Когда нам нужен узор декоратора?

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

Ответ 1

Потоки в Java - подклассы InputStream и OutputStream являются прекрасными примерами шаблона декоратора.

В качестве примера можно записать файл на диск:

File toWriteTo = new File("C:\\temp\\tempFile.txt");
OutputStream outputStream = new FileOutputStream(toWriteTo);    

outputStream.write("Sample text".getBytes());

Затем вам потребуется дополнительная функциональность для записи на диск:

File toWriteTo = new File("C:\\temp\\tempFile.txt");
OutputStream outputStream = 
             new GZIPOutputStream(new FileOutputStream(toWriteTo));

outputStream.write("Sample text".getBytes());

Просто "цепляя" конструкторы, вы можете создать довольно мощные способы записи на диск. Красота таким образом заключается в том, что вы можете добавить различные (в этом примере) реализации OutputStream позже. Кроме того, каждая реализация не знает, как работают другие - все они работают только с одним и тем же контрактом. Это также делает тестирование каждой реализации очень простым в изоляции.


Существует множество примеров "реального мира", в которых можно использовать шаблон декоратора. В верхней части головы несколько примеров:
  • Чтение и запись на диск (выше)
  • Построение элементов пользовательского интерфейса, таких как добавление полос прокрутки в текстовые области и т.д.

В главах First Design Patterns есть еще несколько примеров "реального мира". Кажется, что O'Reilly имеет свой образец главы, который находится на Decorator Pattern, бесплатно; Google обнаружил эту ссылку: PDF

Ответ 2

Два реальных примера:

Системы обновления предметов в Diablo 2 и Final Fantasy 7. Оружие и доспехи имеют гнезда или слоты. Во время игры игрок помещает в эти слоты апгрейды (драгоценные камни, руны или материю). Каждое обновление имеет индивидуальный эффект (скажем, 8 очков урона от огня или 10% маны пиявки). Поэтому, когда вы качаете свой меч, он наносит базовый урон плюс урон, добавленный каждым обновленным обновлением. Это очень близко соответствует рисунку декоратора.

Ответ 3

От группы четырех:

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

...

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

Ответ 4

Посмотрите на описание Фаулера; он дает конкретный пример, относящийся к книгам/видео и декоратору "заемный", вы можете найти его здесь.

Ответ 5

Цель шаблона Decorator заключается в следующем:

Прилагайте дополнительные обязанности к объекту динамически. Декораторы обеспечивают гибкую альтернативу подклассу для расширения функциональности. [через Head First: шаблоны проектирования]

Самым интенсивным использованием декоратора является графический интерфейс и классы java.io. Существует бесплатная глава главы First: Design Patterns о шаблоне декоратора [link], которые содержат некоторые другие примеры:

Хорошо пересмотреть типичное чрезмерное использование наследования, и вы узнаете, как украсить свои классы во время работы, используя форма композиции объекта. Зачем? Как только вы узнаете украшение, вы сможете дать ваш (или кто-то elses) объект новый ответственности без каких-либо изменения кода в классы.

Вы также можете прочитать шаблон декоратора по примеру [PDF], в котором шаблон декоратора используется в оценочном приложении.

Ответ 6

Один из самых крутых - и наиболее буквальных - использования, которые я видел, - это реализовать отмену способности, назад в плохие старые дни одноуровневой отмены. Для векторной программы рисования с несколькими выбранными объектами разных цветов: выполните команду, чтобы изменить все их цвета. И сделать его недействительным. Это было сделано путем применения Decorator, который был вызван в потоке getColor(), так что, когда они были нарисованы, они были нарисованы в новом цвете; по существу, собственные методы getColor() были отменены. Таким образом, они появились в новом цвете. Отменить было так же просто, как удалить Decorator из всех объектов; совершение действия было вопросом применения цвета от Декоратора к объектам, а затем его удаления. Гораздо проще, чем хранить таблицу, в которой были окрашены объекты и какими были их оригинальные цвета.

Ответ 7

Вы просили привести пример из реальной жизни, так что вот вам: скачать (или просмотреть) DonsProxy с github:

мерзавец://github.com/DonBranson/DonsProxy.git

DonsProxy в основном использует шаблон WireTap, чтобы позволить вам наблюдать или извлекать HTTP-трафик, плюс он позволяет вам изменять поведение соединения для имитации неоптимальных соединений. Я использую шаблон Decorator для изменения каналов в зависимости от пользовательских настроек. Параметры командной строки или графического интерфейса (в зависимости от того, какое представление они используют), среди прочего, позволяют вводить задержку и пропускную способность. Когда они вводят задержку, это добавляет LatencyDecorator к каналу; если они ограничивают полосу пропускания, это добавляет ThrottleDecorator к каналу. Поскольку при этом используется шаблон декоратора, они могут смешивать и сопоставлять поведение со своим сердцем.

Ответ 8

Если вы знакомы с разработкой Swing на Java (наряду с другими инструментами GUI), вы увидите, что шаблон декоратора используется много. У вас может быть конструктор, который принимает определенный компонент, а затем добавляет ему функциональность.

Вот хорошая статья, в которой используется Swing в качестве примера.

Ответ 9

Когда необходимо использовать шаблон декоратора?

Используйте Decorator_pattern, если

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

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

Я придумал свой собственный вендинг-автомат.

Описание проблемы: Вычислите цену напитка (чай или кофе), добавив один или несколько ароматов, таких как сахар, лимон и т.д.

Пример кода и пояснения доступны @

Когда использовать шаблон декоратора?