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

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


person Gainster    schedule 30.01.2011    source источник
comment
Вы можете увидеть пример этих двух шаблонов здесь, решающий ту же проблему в Книга GoF (о TextView).   -  person Dherik    schedule 14.02.2017
comment
Просто добавлю свои 2 цента: при чтении ответов ниже вы можете иметь в виду, что DP Decorator может упростить управление подклассами. Вы можете использовать их по отдельности, создавать из них различные комбинации и т. д. Все это в одном классе: классе Decorator. Взгляните на диаграмму UML для этого DP. Например: cdn.journaldev.com/wp-content /uploads/2013/07/   -  person sflr    schedule 29.08.2017
comment
Статья, написанная для ответа на этот вопрос: dzone.com/articles/is-inheritance-dead   -  person nbilal    schedule 28.01.2018
comment
Я предпочитаю объяснять это следующим образом: если вам нужно полиморфное поведение, используйте наследование объектов. Если это обеспечивает дополнительную функциональность, лучше подходит шаблон декоратора.   -  person UT-Fan-05    schedule 28.03.2018


Ответы (6)


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

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

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

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

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

person sloth    schedule 30.01.2011
comment
Я также должен создавать классы декораторов в дизайне. Таким образом, я аналогичным образом мог бы добавить подкласс, так что в чем смысл. - person Gainster; 30.01.2011
comment
статья в Википедии содержит несколько примеров. Конечно, вы должны создавать классы декораторов во время разработки, но вы можете выбрать их динамическое применение во время выполнения. - person sloth; 30.01.2011
comment
@Gainster действительно, здесь ты прав. Самым большим преимуществом Decorator является возможность повторного использования такого декоратора для других классов. Точно так же, как и другие люди в этой теме. - person G. Demecki; 27.10.2015
comment
@Gainster Есть много причин, по которым стоит предпочесть декоратор, среди которых: 1) вы можете повторно использовать один и тот же декоратор в нескольких реализациях одного и того же интерфейса (с наследованием вам придется создавать подклассы для каждой реализации), 2) вы можете протестировать свой декоратор изолированно от украшенного объекта (невозможно с наследованием, чтобы издеваться над родительским классом). Взгляните на: dzone.com/articles/is-inheritance-dead - person nbilal; 28.01.2018

Пример из GoF:

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

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

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

person taskinoor    schedule 30.01.2011

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

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

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

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

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

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

С декораторами вам нужно определить только два декоратора прокрутки и один декоратор границы.

person Don Roby    schedule 30.01.2011

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

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

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

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

person Aaron    schedule 05.03.2013
comment
Это хороший момент... моей первоначальной мыслью было просто использовать интерфейсы для таких классов, но они не такие модульные/проверяемые, как наличие декоратора. - person levininja; 10.07.2014

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

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

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

Родитель->Ребенок->Внук.

Автомобиль->Maruti 800->Maruti 100 (будет иметь функцию Maruti 800, а также новый)

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

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

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

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

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

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

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

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

person Sheo Dayal Singh    schedule 24.08.2017

Гибкость, вот причина IMO.

person Jahan    schedule 30.01.2011