Decorators and Proxies have slightly different intents, but are similar enough in structure that I will treat them as a single pattern. For a discussion on the formal differences, see Five's Weblog.
We want to add behavior to an existing class's methods.
If the class implemented the Strategy Pattern, then we could simply create new strategies. Of course normally the strategy only modifies the behavior of a single method. The Bridge Pattern could be used to change the implementations of all of the methods. But of course this assumes the class implements one of these patterns, that instances will allow you to modify their guts.
Without access to the guts of an object, the Decorator Pattern allows us to change the skin of an object.
A client uses an object that implements the Component interface. The object could be a concrete component or a decorator. The decorator may add some behavior, then forwards the client's request to its delegate. The delegate may be a concrete component or yet another decorator. In fact, the concrete component may ground a long chain of decorators.
In the following scenario a client interacts with a chain of decorators. Note that every object thinks the next object in the chain is the component, because all decorators implement the Component interface.
The first decorator adds behavior to serviceA and serviceB, while the second decorator only adds behavior to serviceB.
Also note that the first decorator adds behavior to serviceA in the form of pre-processing and post-processing, while it only adds pre-processing behavior to serviceB.
See DecoratorDemo.java for an implementation of the above scenario.
Here's the output produced:
See Proxies.
Java uses the Decorator Pattern to add features to I/O streams. (See Java I/O to review streams.) In this context decorators are called filters. For example, here is a fragment of the InputStream hierarchy:
The situation is similar for output streams and character input and output streams (readers and writers).
Here's a sketch of the FilterInputStream, like a true decorator, it implements the abstract read method by forwarding to its delegate:
class FilterInputStream extends InputStream {
protected InputStream in;
public FilterInputStream(InputStream
in) { this.in = in; }
public int read() throws IOException {
return in.read(); }
}
Here's an example of creating a chain of filters (decorators) in front of a file input stream:
DataInputStream is = null;
try {
is = new DataInputStream(
new BufferedInputStream(
new
FileInputStream("myData")));
System.out.println("next = "
+ is.readDouble());
System.out.println("next = "
+ is.readBoolean());
System.out.println("next = "
+ is.readInt());
System.out.println("next = "
+ is.readChar());
} catch(IOException e) {
System.err.println(e.getMessage());
} finally {
try {
is.close();
} catch(IOException e) {
System.err.println(e.getMessage());
}
}
As stated, the Decorator Pattern can be used to add behavior to the methods of an existing class without modifying the class. Specifically, the Decorator Pattern allows us to add behavior to the methods of the ConcreteComponent. But this assumes that the ConcreteComponent at least implements the Component interface. What if this were not the case? Further, what if we had no access to the source code for ComponentClass, so modifications were impossible?
We have seen this problem before: a class provides the desired functionality, but doesn't implement the desired interface. The solution: the Adapter Pattern.
Redraw the Decorator Pattern showing how you would incorporate an adapter.