The Need for the Decorator Pattern:
Decorators can be used to decorate classes at runtime using a form of object composition.This is a good pattern which helps to minimize overuse of inheritance for adding special behaviours to classes. Decorators are primarily used to add flexibility to design. They are used to add more behaviours to existing classes by adding a wrapper around them,without changing the existing code. One needs to be careful in writing a decorator. Too much decoration can make the code lousy,difficult to read,modify and maintain. For instance, consider Java's I/O libraries. They are notoriously difficult for people to understand at first. But if they just saw the classes as a set of wrappers around the abstract class InputStream, life would be simpler..
Learning by example..
1. Recognising the decorators from the Java.IO classes
The InputStream is the abstract component. The FilterInputStream, ByteArrayInputStream, StringBufferInputStream and the FileInputStream are abstract decorators.
Now, PushbackInputStream, BufferedInputStream, DataInputStream and LineNumberInputStream are all concrete decorators.
Now, think about the decorators and the flexibility it adds to the design of Java.IO in the following sentences..(Classes are open for extension but closed for modification)
InputStream in = new BufferedInputStream(new FileInputStream("aFile.txt"));
BufferedInputStream bis = new BufferedInputStream ( new DataInputStream ( new FileInputStream ( "aFile.txt" ) ) ) ;
2. An example of decorating our beverage component by using an abstract decorator 'CondimentDecorator' and a single concrete decorator 'Mocha'. The concrete components add specialized classes (HouseBlend, Espreso). We will see this in more detail in Part II. Consider the following class diagram.
The Beverage is the component which we are interested in decorating here. The CondimentDecorator is the abstract decorator. The Classes Expresso and HouseBlend are concrete components. The Mocha class is a concrete decorator.
Now, look at the following code to understand the power of concrete decorators and the Decorator Pattern itself.
Beverage b1 = new Espresso(); // A type of Beverage, Concrete component
Beverage b2 = new HouseBlend(); //A type of Beverage, Concrete component
b2 = new Mocha(b2); //wrap the beverage with Mocha
Decorators Rule!, More reasons and justifications in Part II..