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 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.