Образец декоратора против подкласса - PullRequest
51 голосов
/ 30 января 2011

Я могу решить проблему добавления функциональности, добавив подклассы, тогда зачем мне использовать шаблон декоратора, в чем реальное преимущество шаблона декоратора?

Ответы [ 6 ]

45 голосов
/ 30 января 2011

Пример из GoF:

Предположим, у вас есть класс TextView. Затем в каком-то месте вам нужно представление с прокруткой текста, поэтому вы создаете подкласс TextView и создаете класс ScrolledTextView. А в каком-то другом месте вам нужна рамка вокруг текстового представления. Таким образом, вы снова создаете подкласс и создаете BorderedTextView. Ну, а теперь в каком-то месте вы хотите границу и прокрутите оба. Ни один из предыдущих двух подклассов не обладает обеими возможностями. Так что вам нужно создать третий. При создании ScrolledBorderedTextView вы фактически дублируете усилие. Вам не нужен этот класс, если у вас есть возможность объединить возможности предыдущих двух. Ну, все может пойти хуже, и это может привести к ненужному взрыву класса.

По сути, используя шаблон декоратора, вы можете добавить любое количество дополнительной ответственности к объекту во ВРЕМЯ РАБОТЫ, чего вы не можете достичь, создав подклассы, не повредив структуру кода.

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

40 голосов
/ 30 января 2011

из Шаблон декоратора в Википедии

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

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

из той же статьи:

Шаблон декоратора альтернатива подклассам. Подклассы добавляют поведение при компиляции время , и изменение влияет на все экземпляры оригинального класса; украшение может обеспечить новое поведение при время выполнения для отдельных объектов .

19 голосов
/ 30 января 2011

В книге GoF Design Patterns указаны два основных преимущества использования декораторов по сравнению с подклассами:

  1. Больше гибкости, чем статическое наследование. Шаблон Decorator предоставляет более гибкий способ добавления обязанностей к объектам, чем при статическом (множественном) наследовании.С помощью декораторов можно добавлять и удалять обязанности во время выполнения, просто подключая и отключая их.Напротив, наследование требует создания нового класса для каждой дополнительной ответственности (например, BorderedScrollableTextView, BorderedTextView).Это порождает много классов и увеличивает сложность системы.Кроме того, предоставление различных классов Decorator для конкретного класса Component позволяет смешивать и сопоставлять обязанности.

    Декораторы также позволяют легко добавлять свойство дважды.Например, чтобы дать TextView двойную границу, просто присоедините два BorderDecorator.Наследование от класса Border дважды в лучшем случае подвержено ошибкам.

  2. Позволяет избегать классов с высокими характеристиками, находящихся высоко в иерархии. Декоратор предлагает оплату по мере использованияподход к добавлению обязанностей.Вместо того, чтобы пытаться поддерживать все предполагаемые функции в сложном, настраиваемом классе, вы можете определить простой класс и постепенно добавлять функциональные возможности с объектами Decorator.Функциональность может быть составлена ​​из простых частей.В результате приложение не должно платить за функции, которые оно не использует.Также легко определить новые типы декораторов независимо от классов объектов, которые они расширяют, даже для непредвиденных расширений.Расширение сложного класса приводит к раскрытию подробностей, не связанных с добавляемыми вами обязанностями.

С моей точки зрения, предотвращение взрыва подкласса является достаточно убедительным.

Если у вас есть TextWindow, к которому вы хотите добавить горизонтальную прокрутку, вертикальную прокрутку и границы независимо и опционально, используя подклассы, вы должны будете определить подклассы для HorizontalScrollingTextWindow, VerticalScrollingTextWindow, HorizontalAndVerticalScrollingTextWindow, BorderedTextWindow, HorizontalScrollingBorderedTextWindow, VerticalScrollingBorderedTextWindow, HorizontalAndVerticaScrollingBorderedTextWindow и т. Д., Если вы заботитесь о порядке прокрутки и окаймления.

Для Decorators вам нужно определить только две прокруткидекораторы и один бордюрный декоратор.

11 голосов
/ 05 марта 2013

Создание подклассов может привести к проблемам с принципом замены Лискова .Декоратор избегает этого.

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

Используя шаблон декоратора и следуя принципу единой ответственности, я могу создать несколько декораторов и сложить их в любом случае, если захочу.Я могу настроить это во время выполнения.При наследовании мне нужно либо создать все возможные ветви (a-> b-> c, а затем a-> c-> b, дублируя код и взорвать количество тестов), либо создать 1 иерархию, а затем добавить еще одну, когда это необходимо,это запускает новый цикл тестирования / выпуска.

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

2 голосов
/ 24 августа 2017

Вот различия, основанные на реальной реализации.

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

1) Подклассификация, в основном, используется в случае расширения функциональности аналогичной группы классов, которая хочет сохранить старые функциональные возможности, а также новые вподклассы и все экземпляры подклассов имеют одинаковую функциональность.Если мы внесем изменения в дочерние классы, и тогда это отразит все исходные классы дочерних классов. Например, иерархическая связь, похожая группа классов.

Parent-> Child-> GrandSon.

Car-> Maruti 800-> Maruti 100 (будет иметь функцию Maruti 800, а также New)

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

Icircle cir = новый RedDecorator (новый круг ()), украшающий круг красным цветом

Icircle cir = новый YellowDecorator (новый круг ()), украшающий круг желтым цветом

Icircle cir = новый RedDecorator (новый YellowDecorator (новый кружок ())), украшающий круг

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

Таким образом, это уменьшает количество классов комбинации.

Вот полезная ссылка для шаблона декоратора

https://www.tutorialspoint.com/design_pattern/decorator_pattern.htm

1 голос
/ 30 января 2011

Гибкость, вот почему ИМО.

...