Decorator pattern versus sub classing

Design PatternsDecorator

Design Patterns Problem Overview


I can solve the problem of adding functionality by adding sub classing then why should I use decorator pattern what's the real advantage of decorator pattern ?

Design Patterns Solutions


Solution 1 - Design Patterns

from Decorator pattern at wikipedia

> The decorator pattern can be used to > make it possible to extend (decorate) > the functionality of a certain object > at runtime.

The whole point of decorator pattern is to dynamically add additional behaviour/functionality, which is of course not possible at design time.

from the same article:

> The decorator pattern is an > alternative to subclassing. > Subclassing adds behavior at compile > time, and the change affects all > instances of the original class; > decorating can provide new behavior at > runtime for individual objects.

Solution 2 - Design Patterns

An example from GoF:

>Suppose you have a TextView class. Then in someplace you want a scrolled text view, so you subclass TextView and create ScrolledTextView class. And in some other place, you want a border around text view. So you subclass again and create BorderedTextView. Well, now in someplace you want border and scroll both. None of the previous two subclasses have both capabilities. So you need to create a 3rd one. When creating a ScrolledBorderedTextView you are actually duplicating the effort. You don't need this class if you have any way to compose the capability of the previous two. Well, things can go worse and these may lead to an unnecessary class explosion.

Basically, by using the decorator pattern you can add any number of additional responsibility to object at RUNTIME which you can not achieve by subclassing without potentially damaging your code structure or adding many duplicate combinations for subclasses.

But one thing, Design patterns are not something that you must use.
Whether a pattern is needed or not is dependent on your particular problem, you want to maintain the code for a long time or not, whether you want to extend or not and on many other factors like these.
And there is no pattern that is useful in all cases.
A pattern (decorator or anything else) suitable for a situation may not be a good choice for another situation.

Solution 3 - Design Patterns

The GoF Design Patterns book identifies two major advantages of using Decorators over subclassing:

> 1. More flexibility than static > inheritance. The Decorator pattern > provides a more flexible way to add > responsibilities to objects than can > be had with static (multiple) > inheritance. With decorators, > responsibilities can be added and > removed at run-time simply by > attaching and detaching them. In > contrast, inheritance requires > creating a new class for each > additional responsibility (e.g., > BorderedScrollableTextView, > BorderedTextView). This gives rise > to many classes and increases the > complexity of a system. Furthermore, > providing different Decorator > classes for a specific Component > class lets you mix and match > responsibilities. >
> Decorators also make it easy to add > a property twice. For example, to > give a TextView a double border, > simply attach two BorderDecorators. > Inheriting from a Border class twice > is error-prone at best. > > 2. Avoids feature-laden classes high up > in the hierarchy. Decorator offers a > pay-as-you-go approach to adding > responsibilities. Instead of trying > to support all foreseeable features > in a complex, customizable class, > you can define a simple class and > add functionality incrementally with > Decorator objects. Functionality can > be composed from simple pieces. As a > result, an application needn't pay > for features it doesn't use. It's > also easy to define new kinds of > Decorators independently from the > classes of objects they extend, even > for unforeseen extensions. Extending > a complex class tends to expose > details unrelated to the > responsibilities you're adding.

From my point of view, preventing subclass explosion alone is quite compelling.

If you have a TextWindow to which you want to add horizontal scrolling, vertical scrolling, and borders all independently and optionally, using subclasses, you'd have to define subclasses for HorizontalScrollingTextWindow, VerticalScrollingTextWindow, HorizontalAndVerticalScrollingTextWindow, BorderedTextWindow, HorizontalScrollingBorderedTextWindow, VerticalScrollingBorderedTextWindow, HorizontalAndVerticaScrollingBorderedTextWindow, and more if you care about the order of scrolling and bordering.

With Decorators, you only need to define two scrolling decorators and one border decorator.

Solution 4 - Design Patterns

Subclassing can lead to issues with the Liskov substitution principle. The decorator avoids this.

Another advantage of the decorator is that you are writing (forced to write) to an interface. This makes things easier for testing. It is true that your object hierarchy can also be written to an interface and thus have some of the same advantages, however, I can test a single implementation of a decorator class in isolation. I cannot do the same with a subclass because I will always get the whole hierarchy back to the base class. I am unable to test the new code in isolation.

Using the decorator pattern and following the single responsibility principle, I can create several decorators and stack them anyway I wish. I can configure that at runtime. In inheritance I either have to create every possible branch (a->b->c then a->c->b, thus duplicating code and exploding the number of tests), or I create 1 hierarchy then add another when needed, but this triggers a new test/release cycle.

This is why you would want to use the decorator pattern instead of subclassing.

Solution 5 - Design Patterns

Here is the differences based on the real implementation.

Decoration is an alternative way of sub classing to extend the functionality of existing classes. Here is some scenario where we should use sub classing or decorator.

  1. Sub classing mainly used in the case of extend the functionality of similar group of classes which wants to retain the old functionality as well as new in the sub classes and all the instances of the sub classes share the same functionality. If we make the changes of child classes and then it will reflect all the instaces of child classes.Such as a hierarchy relation ship, similar group of classes.

    Parent->Child->GrandSon.

    Car->Maruti 800->Maruti 100( will have the feature of Maruti 800 as well as New)

  2. Decorator pattern is used to decorate the existing classes without changing the old behavior.Such as a class circle have plain border but we need to decorate it with red border,after some time some user wants circle with yellow color and some user wants circle with green border and some user wants red and yellow border circle and some user wants red and green border circle etc,for this it is the perfect pattern as it will reduces no of combination classes.Below is the example.

Icircle cir=new RedDecorator(new circle()) decorating the circle with red color

Icircle cir=new YellowDecorator(new circle()) decorating the circle with Yellow color

Icircle cir=new RedDecorator(new YellowDecorator(new circle())) decorating the

circle with red and Yellow, here we do not need to create RedAndYellow class decorator. same way we can decorate the circle with other set of combination without creating new set of combination classes.

In this way it reduces the no of combination classes.

Here is the useful link for decorator pattern

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

Solution 6 - Design Patterns

Flexibility, that's the reason IMO.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGainsterView Question on Stackoverflow
Solution 1 - Design PatternsslothView Answer on Stackoverflow
Solution 2 - Design PatternstaskinoorView Answer on Stackoverflow
Solution 3 - Design PatternsDon RobyView Answer on Stackoverflow
Solution 4 - Design PatternsAaronView Answer on Stackoverflow
Solution 5 - Design PatternsSheo Dayal SinghView Answer on Stackoverflow
Solution 6 - Design PatternsJahan ZinedineView Answer on Stackoverflow