Skip to main content

The “Gang of Four” Decorator Pattern: What Is Its Appropriate Use?

Printer-friendly version
The first point again emphasizes the dynamic aspect and the focus on individual objects. This seems a very different purpose than Generalization which is about static decomposition that applies to all objects in the set. The text doesn’t, of course, say that it is wrong to use Decorator for static typing.

The second point further reinforces this dynamic or transient quality, but focuses on removing the functionality rather than adding it.

The third point seems to directly address the interpretation of Decorator as an alternative to Generalization. Here, there is an explicit statement that it is to be used when Generalization is “impractical” and specifically points to the crosstab problem which exists when there are a multiple, independent aspects of functionality which can be combined onto a single object. It also mentions the case where the class definition is unavailable for Generalization in some way. Thus, in this section, it seems that Decorator is not offered as a general alternative for Generalization, but is suggested in cases where Generalization is not going to work well or is not possible.

One of the cases where Generalization does not work well is where the functionality is dynamic or transient since Generalization is about static classification. A class can have state dependent behavior without Decorators, but the behavior is always a part of the class definition whether the state is active or not. If there are too many states or options, the class can be become bloated. This is the Dynamic Variation functionality described above.

The other notable place where Generalization does not work well is where there are multiple alternatives that can be freely combined, i.e., the Crosstab functionality described above. While it is possible to construct hierarchies for this type of functionality, such hierarchies are undesirable because it is necessary to duplicate functionality across branches and they are often fragile in response to changing requirements.

One might also note that one-sided functionality does not fit very well with Generalization since one wants to instantiate terminal subclasses in the tree, but with one-sided functionality, there is only unique functionality on one side of the branch. This implies the need for a bunch of subclasses which contain nothing to represent the state when the functionality is not present, which is clearly undesirable.

Thus, for Dynamic Variation functionality and for options involving one-sided functionality, it can be recognized that Generalization is often not a good solution and Decorator offers itself as a pattern which addresses this type of problem well. But, what about Crosstab functionality?

One key question would seem to be whether Crosstab functionality was common in static decompositions. This would seem to depend on the nature of the decomposition which one performs prior to considering whether to use Decorator or some other approach. If the decomposition fails to identify separate, coherent spheres of responsibility which can be properly removed to their own class hierarchy via Delegation, then one is certainly likely to encounter complex objects with complex sets of crosstab functionality possibilities. However, if one does identify and separate those Delegates, then the complexity of the options remaining in the primary object is reduced correspondingly and it seems likely the crosstab character can be eliminated.

GoFDecorator_20100222.pdf127.66 KB