I try to decorate my imagination as much as I can.
Pictures deface walls more often than they decorate them.
William Wordsworth (Poet and a guy who really understood bandwidth)
The Decorator pattern wasn't developed with a web designer or developer in mind, but it could well have been. A few years back, we developed a web site and were cognizant of the fact that periodically we'd have to update it. The design was set up so that substitution of one element for an updated one was fairly simple, and it required no major change in the code or structure. Because we didn't have to update it too often, this wasn't much of a problem. However, had we needed to update elements or features on a fairly regular basis, our design would have left a good deal to be desired.
Imagining situations where you need to update or change certain parts of a web site on a regular basis isn't difficult. If your client is a retailer with regular advertising such as weekly specials and new products introduced periodically, you want to have flexibility in your web design and structure. You may want to use features of your basic structure that assure change is easily accommodated, but you don't have to alter the basic structure itself in any way.
The Decorator pattern addresses the issue of maintaining the structure while having the ability to make changes by decorating the different components that make up the application. The decorations are composed of descriptions and/or methods used to wrap different objects in the application. As you will see, this design pattern allows you to mix and match all the different components and decorations to optimize flexibility and expandability, while core structure classes remain unaltered.
We can understand the Decorator pattern in terms of two key features. Often, developers want to add unique responsibilities for an object without adding those same responsibilities to the whole class. Among other design patterns, the Decorator pattern's characterized by adding unique responsibilities. The identifying characteristic of the Decorator pattern is to add responsibilities in a uniquely Decorator fashion. Wrapping a component in an object that adds a responsibility follows a couple of guidelines:
Decorators can appear wherever a component object can.
At runtime, you can mix and match combinations of decorators as needed.
To understand the Decorator design pattern's key features, you need to consider some alternatives to implementing the work the pattern does. Essentially, your project requires that you add new features and responsibilities to individual objects rather than the entire class. To do so using inheritance would bloat the class and change the structure with each new feature. Every single object would inherit all of the features and functionality of every other object, and that's not what you want.
In this chapter, you will see the term "component" a good deal. The reference to component here is wholly unrelated to the components in Flash, used for UIs, Media, Data and other purposes. In the context of this chapter, a component refers to a concrete instance that is decorated with another concrete instance called a decorator. So, for the time being, don't think of components as anything other than something that gets decorated. (In the last application example of a Decorator design pattern in this chapter, you'll be using Flash UI components, but by then you'll be able to distinguish the different kind of components.)
Imagine you're setting up an automobile dealership site. You can choose between different models of autos and add different features—options. You can set up options such as an MP3 player, Global Positioning System (GPS), cloth, vinyl or leather seat covers, and different kinds of alarm systems. If you use inheritance, every one of those options would have to be in every object. What's more, you'd need to have all the models in your main class as well. That's absurd! Why would anyone need both cloth and vinyl seats or be both a Ford Escape and a Chevrolet Malibu? Then, if a new option were introduced, you'd have to bloat the class with yet another option for every single object. However, if you can just wrap a single responsibility around a component when and if you need it, you can keep your program slim, trim and ready to adapt.
The key to understanding the Decorator design pattern is to understand that it uses inheritance and employs abstract classes; however, as you know from Chapter 2, ActionScript 3.0 doesn't support abstract classes. You can create classes that work like abstract classes, simply by not instantiating them directly. In fact, that's what an abstract class is to some extent—a class that you do not instantiate but can extend. They work something like an interface, but while you can implement an interface and its abstract methods, you cannot extend it. (You were introduced to using interfaces in Chapter 1, and in Chapter 5, you will be using a design pattern that employs interfaces.)
Lack of support of abstract classes is a sore point with some Flash and Flex developers. Before firing off an impassioned email to Adobe, though, first take a look at the ECMAScript Rev 4 specs. These specifications don't exactly support abstract classes either, at this point in time.
Why are abstract classes important for the Decorator pattern? Like interfaces, you can create abstract methods that can be implemented in different ways. At the same time, you can use them to create subclasses so that core properties can be inherited in ways not possible with interfaces alone.
The Decorator outlined in the class diagram notation shows two key elements: component and decorator. The component represents what's to be decorated, and the decorator is the abstract class for the concrete decorations. The concrete component is what's actually decorated, and the concrete decorations are the actual decorations. All of the concrete decorations and the concrete component are subclassed from the same source. Keeping that in mind, take a look at the class diagram in Figure 4-1:
In the most basic sense, the component is the Christmas tree, and the decorations are the ornaments. Each concrete decorator wraps the tree and is subclassed from the same source as the tree. A better way to think about components and decorators is more like the nesting dolls from Japan and Russia. The innermost doll is the component, and it's placed into a decorator. Then the component and decorator are placed into another decorator, and then into the next decorator. Figure 4-2 shows this model.
Probably the most important thing to remember about the Decorator pattern is that its purpose is to allow additional elements to be added to a class without altering the base class. So instead of making changes by changing the class, the class is decorated with subclasses that don't interfere with the class from which the decorators were derived.