Design Patterns

Decorator



Design Pattern Type: Structural

GoF Statement of Intent:


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



Allows new or additional behavior to be added to an existing object dynamically at run time. We say that the new behavior "decorates" the existing object. This requires some groundwork to be done at design time. The additional behavior classes are made subclasses of a "decorator" class which is itself also a sub-class of the object (or its parent class) they are to decorate. The decorator class has added a pointer to the parent class of the object type that it decorates. The decorator is then instantiated by passing a pointer to the object it will decorate. The decorator then receives function calls meant for the object and either passes the calls on to the object or modifies the behavior as required for the object. The way it is organized multiple decorators can be "stacked" or "nested" to add more behavior patterns. This is an alternative to adding extra behavior by adding more sub-classes. Java I/O streams actually follow this pattern.

UML Diagram:

Discussion and In-class Example:

In the Decorator Design Pattern we used the example of the Starbuzz Coffee shop which had several subclasses of Beverage, but needed to create an unwieldy number of subclasses to handle all the different condiment combinations. The solution to the problem was the Decorator. A new Decorator subclass (CondimentDecorator) of Beverage was created and then all the condiments became subclasses of that parent. The only reason for using inheritance here was to insure that all the objects being handled were of the same type to increase flexibility.

Now we could place a reference to another Beverage in the Beverage superclass and nest one of the "real" beverage objects (HouseBlend, DarkRoast, Decalf, Espresso, and even later Tea) inside of any number of "layers" of condiments. In this way we could add new functionality to the "real" beverage object without having to modify the class itself.

The Decorator pattern is usually used in conjunction with either the Abstract Factory or the Builder pattern to ensure that the Decorators are correctly organized and that the correct reference to the outer most Decorator is returned to the application.