Recipe 18.5. Implementing the Decorator PatternProblemYou want to apply the decorator pattern using AspectJ. SolutionThe decorator pattern extends the behavior of a classes methods while maintaining its existing public interface without the class knowing or caring about the extension. Example 18-7 shows an abstract aspect that lays the foundation of the decorator pattern that can then be applied using more specific subaspects in a target application. Example 18-7. Using aspects to define the decorator patternpublic abstract aspect DecoratorPattern { public interface DecoratedComponent { }; private boolean DecoratedComponent.decorated = false; public void DecoratedComponent.setDecorated(boolean decorated) { this.decorated = decorated; } public void DecoratedComponent.isDecorated(boolean decorated) { return this.decorated ; } } DiscussionFigure 18-11 shows the structure of the DecoratorPattern abstract aspect and the interfaces and behavior that it defines to support the decorator design pattern. Figure 18-11. The DecoratorPattern aspect and the interfaces and behavior it defines for the design pattern's rolesThe DecoratorPattern abstract aspect defines the DecoratedComponent interface to provide a common base interface for all classes that are to be decorated implement. The decorated field is introduced into those classes along with a pair of accessor and modifier methods. Example 18-8 shows how the abstract DecoratorPattern aspect could be applied for a specific application. The TexTDisplayDecorator specifies that the Textdisplay class can be decorated, and that the display(..) method is decorated before and after the method is called if the particular object is decorated. Example 18-8. Applying the DecoratorPattern to an application's classespublic aspect TextDisplayDecorator extends DecoratorPattern { declare parents : TextDisplay implements DecoratedComponent; public pointcut selectDecorators(Object object) : call(public void TextDisplay.display(String)) && target(object); before(Object object) : selectDecorators(object) && if(((DecoratedComponent)object).getDecorated) { System.out.print("<Decoration>"); } after(Object object) : selectDecorators(object) && if(((DecoratedComponent)object).getDecorated) { System.out.print("</Decoration>"); } } Figure 18-12 shows the effects when the TextdisplayDecorator aspect, shown in Example 18-8, is applied to the Textdisplay class. Figure 18-12. The effects of applying the decorator pattern to the TextDisplay classFigure 18-13 shows how the new decorated behavior of the Textdisplay class behaves in an example application. Figure 18-13. Using the decorated behavior of the TextDisplay classSee AlsoThe recipes in Chapter 16 contain more details on the mechanisms by which existing classes can be extended using aspects and the declare keyword; the call(Signature) pointcut is covered in Recipe Recipe 4.1; exposing join point context is examined in Recipe 13.2; the args(Type or Identifier) pointcut is described in Recipe 11.3. |