Decorator Pattern

Intent: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

While reading the Gang Of Four book on CD I noticed that the original name of this pattern was "Wrapper". -- Dave Mitchell

This pattern was also called shadowing in LPC.



This pattern can also be used as a way to refactor a complex class into smaller pieces. Even if you don't need to attach responsibilities dynamically it can be clearer to have each responsibility in a different class. Somewhat like Mix Ins. -- Christian Taubman


The "Adapter" pattern is also known as "Wrapper" pattern (Wrapper Pattern). Is Wrapper/Adapter/Decorator the same pattern?

No. Adapter Pattern is used to convert the interface of an object into something else. Decorator Pattern is used to extend the functionality of an object while maintaining its interface. Both of these are probably sometimes called Wrapper Pattern since both of them do "wrap" an object.


My understanding is that the Decorator Pattern does not refer to just any dynamic modifications to a class. My understanding is that it works like this:

You have an instance, and you put another instance inside of it. They both support the same (or similar) interfaces. The one on the outside is a "decorator."

You use the one on the outside. It either masks, changes, or pass-throughs the methods of the instance inside of it.

(Jim Coplien calls this a Letter/Envelope idiom, with the inner instance being the letter and the outer instance being the envelope.)

This is very different from what I've heard people say "the Decorator Pattern" means - I've heard people saying that pretty much anything that dynamically changes a class is an instance of "the Decorator Pattern."

So for instance, if you dynamically change a class at run-time in a language that lets you do that, you are now using, "The Decorator Pattern." If there's a feature of a language that lets you add a method to a class at run-time, they're calling that use of "the decorator pattern."

Reality check?


The description above implies that decorating an object changes its behaviour but not its interface. Is that necessarily true? For example, say you have a spell-check dictionary object. You want to get statistics on the most commonly misspelled words, so you wrap your spell-check dictionary in an envelope that tracks statistics. It exposes new methods for reading the stats.

Now it's true that the original client of the spell-check dictionary is in no way aware of the expanded interface. So from its perspective, your modification has not changed the interface. Isn't this an example of the Decorator Pattern?


In python, the 'random' module has a shuffle function which shuffles a list: random.shuffle(lyst) but what you mean is lyst.shuffle(); so importing the random module should add the shuffling behaviour to lists. Is this the Decorator Pattern?


An example of this pattern is how java.io's Readers and Writers work.


The difference that I see between a Decorator Pattern and subclassing is that you can decorate any class that implements an interface with a single class. Say I wanted to give myself a java.util.Map that printed a message whenever I added or removed a key. If I only ever actually used java.util.Hash Map I could just create Printing Map as a subclass of Hash Map and override put & remove. But if I want to create a printing version of Tree Map then I either create Printing Tree Map (which has almost identical code to Printing Map (which should itself become Printing Hash Map)), or I create a Map decorator.

In short, you are trading "have to write pass-throughs for every method, not just the ones you're changing & do 2 step object creation", for "have to write a subclass for each concrete class you want to change". This goes from helpful to imperative if you are writing a library for others to use.


In java jdk 1.3 added dynamic proxy

that is a great way to "decorate" any object

author has added pre-method / post-method processing, which is decorating the instance


The term "wrapper" its used for several software design patterns, so an alternative, more specific identifier, should be used.

The Decorator Design Pattern has several requirements.

(1) An object that requires the extension.

Example:

A window control that requires additional optional features like:

horizontal scrollbar

vertical scrollbar

titlebar

footerbar or statusbar

other

An example with an Object Oriented C style pseudocode:

public class WindowClass { // ... } // class

(2) Several objects that support the extension by "decoration". Usually, those objects share a common interface, traits, or superclass, and sometimes, additional, intermediate superclasses .

/* abstract */ public class WindowDecoratorClass { // ... } // class

/* concrete*/ public class WindowTitleBarClass: extends WindowDecoratorClass { // ... } // class

/* concrete*/ public class WindowStatusBarClass: extends WindowDecoratorClass { // ... } // class

/* abstract */ public class WindowScrollbarClass: extends WindowDecoratorClass { // ... } // class

/* concrete*/ public class WindowHorizontalScrollbarClass: extends WindowScrollbarClass { // ... } // class

/* concrete*/ public class WindowVerticalScrollbarClass: extends WindowScrollbarClass { // ... } // class

(3) The decorated object (class or prototype instantation), and the decorator objects have one or several common features. In order to enssure that functuonality, the decorated object & the decorators have a common interface, traits, or class inheritance.

In the next example, the "Draw();" method & the "Get Description();" method are the features that are the requirement, and are defined by the "Drawing Control Interface",

public interface WindowDecoratorInterface { // ...

public String GetDescription() { ... }

public void Draw() { ... }

// ... } // interface

public class WindowClass: implements WindowDecoratorInterface { public String GetDescription() { ... }

public void Draw() { ... } } // class

/* abstract */ public class WindowDecoratorClass: implements WindowDecoratorInterface { public String GetDescription() { ... }

public void Draw() { ... } } // class

/* concrete*/ public class WindowTitleBarClass: extends WindowDecoratorClass { public String GetDescription() { ... }

public void Draw() { ... } } // class

/* concrete*/ public class WindowStatusBarClass: extends WindowDecoratorClass { public String GetDescription() { ... }

public void Draw() { ... } } // class

/* abstract */ public class WindowScrollbarClass: extends WindowDecoratorClass { public String GetDescription() { ... }

public void Draw() { ... } } // class

/* concrete*/ public class WindowHorizontalScrollbarClass: extends WindowScrollbarClass { public String GetDescription() { ... }

public void Draw() { ... } } // class

/* concrete*/ public class WindowVerticalScrollbarClass: extends WindowScrollbarClass { public String GetDescription() { ... }

public void Draw() { ... } } // class


See original on c2.com