Recipe 18.4. Implementing the Bridge PatternProblemYou want to apply the bridge pattern using AspectJ. SolutionThe bridge pattern decouples a class from the underlying characteristics of one particular implementation so different implementations can be applied without affecting the class's clients. Example 18-6 shows how to define an application specific bridge pattern aspect. Example 18-6. Bridging between an implementation independent window and the means by which it is implemented using a specific windowing systempublic class Window { public void drawText(String text) { } public void drawRect( ) { } } public aspect XWindowBridge perthis(captureAllBridgedCalls( )) { private XWindow imp = new XWindow( ); public pointcut captureDrawText(String text) : execution(public void Window.drawText(String)) && args(text); public pointcut captureDrawRect( ) : execution(public void Window. drawRect( )); public pointcut captureAllBridgedCalls( ) : captureDrawText(String) || captureDrawRect( ); void around(String text) : captureDrawText(text) { imp.drawText(text); } void around( ) : captureDrawRect( ) { imp.drawLine( ); imp.drawLine( ); imp.drawLine( ); imp.drawLine( ); } } DiscussionFigure 18-9 shows the structure of the XWindowBridge aspect and the behavior that it defines to support the bridge design pattern. Figure 18-9. The XWindowBridge aspect's structureThe XWindowBridge aspect captures all of the methods on the Window class that need to be channeled to specific calls on the XWindow class. For example, the drawRect( ) method on the Window class results in four calls on the XWindow class, but by using the bridge pattern the Window class does not need to have those calls hard coded into its behavior. In Example 18-6, the Window class does not know exactly how it is going to be implemented on different systems, but that is all taken care of by the XWindowBridge aspect. By using the perthis(..) aspect instantiation policy, a new aspect is created for every new bridged Window object as specified by the captureAllBridgedCalls( ) pointcut. This means that every Window object has its own copy of the XWindow implementation object. If you wanted to share the XWindow object across multiple Window objects, then all you need is to delete the perthis(..) policy and remove the redundant captureAllBridgedCalls( ) pointcut definition. If another means were used for drawing windows, then a separate aspect that bridges the calls on the Window class differently could be created and woven into the application instead of the XWindowBridge aspect. Figure 18-10 shows how the new bridged behavior of the Window class behaves in an example application. Figure 18-10. Using the bridged behavior of the Window classSee AlsoThe execution(Signature) pointcut is explained in Recipe 4.4; the args([Types | Identifiers]) is explained in Recipe 11.3; the around( ) form of advice is shown in Recipe 13.4; Recipe 14.2 explains perthis(Pointcut) aspect instantiation policy; specifying the aspects that are built into an application at compile time is covered in Recipe 2.6. |