Decorator Design Pattern – Newbie Guide and Examples

design-patternsobject-orientedprogramming-languages

I was reading a programming article and it mentioned the Decorator pattern. I've been programming for awhile but without any kind of formal education or training, but I'm trying to learn about the standard patterns and such.

So I looked up the Decorator, and found a Wikipedia article on it. I now understand the concept of the Decorator pattern, but I was a bit confused by this passage:

As an example, consider a window in a
windowing system. To allow scrolling
of the window's contents, we may wish
to add horizontal or vertical
scrollbars to it, as appropriate.
Assume windows are represented by
instances of the Window class, and
assume this class has no functionality
for adding scrollbars. We could create
a subclass ScrollingWindow that
provides them, or we could create a
ScrollingWindowDecorator that adds
this functionality to existing Window
objects. At this point, either
solution would be fine.

Now let's assume we also desire the
ability to add borders to our windows.
Again, our original Window class has
no support. The ScrollingWindow
subclass now poses a problem, because
it has effectively created a new kind
of window. If we wish to add border
support to all windows, we must create
subclasses WindowWithBorder and
ScrollingWindowWithBorder. Obviously,
this problem gets worse with every new
feature to be added. For the decorator
solution, we simply create a new
BorderedWindowDecorator—at runtime, we
can decorate existing windows with the
ScrollingWindowDecorator or the
BorderedWindowDecorator or both, as we
see fit.

OK, when they say to add borders to all windows, why not just add functionality into the original Window class to allow for the option? The way I see it is, subclassing is just for adding specific functionality to a class, or overriding a class method. If I needed to add functionality to all existing objects, why wouldn't I just modify the superclass to do so?

There was another line in the 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
run-time for individual objects.

I don't get where they say "…the change affects all instances of the original class" — how does subclassing change the parent class? Isn't that the whole point of subclassing?

I'm going to assume that the article, like many Wiki's, is just not written clearly. I can see the usefulness of the Decorator in that last line – "…provide new behavior at run-time for individual objects."

Without having read about this pattern, if I needed to change behavior at run-time for individual objects, I would have probably built some methods into the super- or subclass to enable/disable said behavior. Please help me really understand the usefulness of the Decorator, and why my newbie thinking is flawed?

Best Answer

The decorator pattern is one that favours composition over inheritance [another OOP paradigm that is useful to learn about]

The main benefit of the decorator pattern - over subclassing is to allow more mix & match options. If you have, for instance, 10 different behaviours that a window can have, then this means - with subclassing - you need to create every different combination, which will also inevitably include a lot of code reuse.
However, what happens when you decide to add in a new behaviour?

With the decorator, you just add a new class which describes this behaviour, and that's it - the pattern allows you to effectively drop this in without any modification to the rest of the code.
With sub-classing, you've got a nightmare on your hands.
One question you asked was "how does subclassing change the parent class?" It's not that it changes the parent class; when it says an instance, it means any object you've 'instantiated' [if you're using Java or C#, for instance, by using the new command]. What it's referring to is, when you add these changes to a class, you've got no choice for that change to be there, even if you don't actually need it.

Alternatively, you can put all his functionality into a single class with it turned on/off via flags... but this ends up with a single class that becomes larger and larger as your project grows.
It's not unusual to start your project this way, and refactor into a decorator pattern once you hit an effective critical mass.

An interesting point that should be made: you can add the same functionality multiple times; so you could, for instance, have a window with double, triple or whatever amount or borders as you require.

The major point of the pattern is to enable run-time changes: you may not know how you want the window to look until the program is running, and this allows you to easily modify it. Granted, this can be done via the subclassing, but not as nicely.
And finally, it allows for functionality to be added to classes that you may not be able to edit - for example in sealed/final classes, or ones provided from other APIs

Related Topic