O'Reilly logo

ActionScript 3.0 Design Patterns by Chandima Cumaranatunge, William Sanders

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Key OOP Concepts Used with the Decorator Pattern

Sometimes when you think about key OOP concepts such as inheritance, you have to consider its larger consequences. The upside of inheritance is that once a superclass has been established, all of the subclasses inherit its features. However, you may not want or need all of the "stuff" for every subclass from a superclass. If you want to add functionality to an object, subclassing may not be the way to go, because everything else subclassed from the same superclass may be unnecessarily burdened by unused functionality.

Unwanted Inheritance

At the end of this chapter, you will see an example of a car dealership where users select models of cars with a choice of options for those cars. If all the options were derived from a superclass, that would mean that every car would have all the options, whether or not you wanted them. One option in the example is a rear view camera used with minivans and large SUVs with limited rear vision. Such an option would be superfluous on a sports car such as a Chevrolet Corvette, Morgan, or Ferrari. However, with subclassing, that's exactly what would happen. Every subclass gets everything from the superclass. So here's a case where we'd have to look beyond simple inheritance. Depending on how the application's written, even the components would all have the same features. A pickup truck would be subclassed from the same component as a luxury car—both inheriting features they don't want and wouldn't use.

Wrapping Responsibilities

The Decorator design pattern is also known as the Wrapper pattern. The concept of "wrapping" is at the heart of the Decorator design pattern. So what does it mean to "wrap" one object in another? One way to think about wrapping is to imagine wrapping a gift. The wrapper transforms the gift, but the gift does not inherit the characteristics of the wrapper—it only uses the wrapping. Unlike subclassing, which extends one class into another, wrapping allows one object to use another's characteristics without extending either the wrapped object or the object doing the wrapping.

The wrapping with which most ActionScript programmers are familiar is that used for transforming data types from one type to another. For example, the Number class can wrap a string variable, and then that variable has the characteristics of the Number class. Figure 4-3 illustrates a common wrapper function:

Number class wrapping String class

Figure 4-3. Number class wrapping String class


When we look at wrapping one object with another object, we can think of it as a class intercepting API calls intended for a specific instance of another class. The example in Figure 4-3 shows that the Number class is intercepting a call to an instance of the String class. The result is that the l variable, an unsigned integer, is able to accept the assignment of the s variable as a number. That's because the s variable is wrapped in a Number class, and is treated as a number.

Using the Decorator class, components are wrapped in decorators. The wrapping class is a concrete instance of a decorator, and the wrapped class is an instance of the concrete component class. Thus, the concrete component now "contains" the characteristics of the wrapper, but the characteristics are not inherited. Figure 4-4 shows an example.

Concrete decorator wrapping concrete component

Figure 4-4. Concrete decorator wrapping concrete component

The concrete component that's wrapped by another class borrows characteristics of the wrapping class. When those characteristics are not needed, the instance of the concrete class is simply instantiated without being wrapped.

Flexibility and Adaptability

One good OOP practice is to create your classes so that they can be extended but not changed. If a class is changed, especially one with subclasses, you can quickly destroy an application. So the trick is to set up your classes so that it's easy to extend them, yet keep them safe from alteration.

The Decorator design pattern allows you to do this. The model is grounded in a single class that is the superclass to all others. This core class is an abstract component class. An abstract decorator class is subclassed from this class, re-implementing the core methods. (In the context of ActionScript 3.0, the abstract nature of the class is simulated by using the override statement when re-implementing methods in subclasses.) All the other concrete component and decorator classes have the same root superclass, even though the decorator classes are subclassed from the abstract decorator class, and the component classes are directly from the abstract component class. So, when the concrete component objects are wrapped in concrete decorator objects, both objects share the same root superclass. Thus, the decorated objects can keep the core object unmodified while changing its responsibilities.

In a larger OOP framework, the Decorator pattern can add and subtract functionality from an object by wrapping selected components with selected decorators. Second, it can add more than a single functionality to an object by wrapping one wrapper inside another wrapper. As a result, the design pattern can change functionality without changing structure.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required