Intent: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
The "Adapter" pattern is also known as "Wrapper" pattern (). Is Wrapper/Adapter/Decorator the same pattern?
While reading the book on CD I noticed that the original name of this pattern was "Wrapper". --
See also: , ,
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 s. --
Also see
The "Adapter" pattern is also known as "Wrapper" pattern (). Is Wrapper/Adapter/Decorator the same pattern?
No. is used to convert the interface of an object into something else. is used to extend the functionality of an object while maintaining its interface. Both of these are probably sometimes called since both of them do "wrap" an object.
My understanding is that the 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.)
- (Jim Coplien calls this a Letter/Envelope idiom, with the inner instance being the letter and the outer instance being the envelope.)
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 ?
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 ?
An example of this pattern is how java.io's Readers and Writers work.
The difference that I see between a 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. I could just create PrintingMap as a subclass of and override put & remove. But if I want to create a printing version of then I either create PrintingTreeMap (which has almost identical code to PrintingMap (which should itself become PrintingHashMap )), 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
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 "GetDescription ();" method are the features that are the requirement, and are defined by the "DrawingControlInterface ",
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