Decorator Pattern - Key OOP Concepts Used with the Decorator Pattern (Page 4 of 4 )
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 the subclasses inherit its features. However, you may not want or need all 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.
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.
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, theNumberclass can wrap a string variable, and then that variable has the characteristics of theNumber class. Figure4-3 illustrates a common wrapper function:
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 theNumberclass is intercepting a call to an instance of theStringclass. The result is that the 1variable, an unsigned integer, is able to accept the assignment of thesvariable as a number. That’s because thesvariable is wrapped in aNumberclass and 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.
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 theoverridestatement 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.
Please check back next week for the continuation of this article.
DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.