Decorator
Allow new/additional responsibility to be added to an existing object dynamically. Decoratores provide a flexible alternative to subclassing for extending functionality.
Introduction
Decorator, a structual pattern also known as wrapper(acts as an interface between its caller and the wrapped code), adds additional functionality to a class at runtime through composition. Decorators are alternative to subclassing which add behaviour at compile time. By wrapping, it allows us to add things to the component without requireing every subclass to inherit these new qualities. Each decorator wraps a component, which means the decorator has an instance variable that holds a reference to a component.
where subclassing would result in an exponential rise of new classes.
- allows us to add things to a component without requiring every subclass to inherit these new qualities.
- Function added at runtime through composition.
- We want an object to do something new, not its class
- "Classes should be open for extension, but closed for modification
Motivation
Sample Code
window/scrolling scenario
// the Window interface interface Window { public void draw(); // draws the Window public String getDescription(); // returns a description of the Window } // implementation of a simple Window without any scrollbars class SimpleWindow implements Window { public void draw() { // draw window } public String getDescription() { return "simple window"; } }
The decorator classes
// abstract decorator class - note that it implements Window abstract class WindowDecorator implements Window { protected Window decoratedWindow; // the Window being decorated public WindowDecorator (Window decoratedWindow) { this.decoratedWindow = decoratedWindow; } } // the first concrete decorator which adds vertical scrollbar functionality class VerticalScrollBarDecorator extends WindowDecorator { public VerticalScrollBarDecorator (Window decoratedWindow) { super(decoratedWindow); } public void draw() { drawVerticalScrollBar(); decoratedWindow.draw(); } private void drawVerticalScrollBar() { // draw the vertical scrollbar } public String getDescription() { return decoratedWindow.getDescription() + ", including vertical scrollbars"; } } // the second concrete decorator which adds horizontal scrollbar functionality class HorizontalScrollBarDecorator extends WindowDecorator { public HorizontalScrollBarDecorator (Window decoratedWindow) { super(decoratedWindow); } public void draw() { drawHorizontalScrollBar(); decoratedWindow.draw(); } private void drawHorizontalScrollBar() { // draw the horizontal scrollbar } public String getDescription() { return decoratedWindow.getDescription() + ", including horizontal scrollbars"; } }
main program
public class DecoratedWindowTest { public static void main(String[] args) { // create a decorated Window with horizontal and vertical scrollbars Window decoratedWindow = new HorizontalScrollBarDecorator ( new VerticalScrollBarDecorator(new SimpleWindow())); // print the Window's description System.out.println(decoratedWindow.getDescription()); } }
Example
- Decorating our Beverages
- Java I/O
References
Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. ISBN 0-201-63361-2. http://www.dofactory.com/Patterns/PatternDecorator.aspx