Recipe 18.2. Implementing the Flyweight PatternProblemYou want to apply the flyweight pattern using AspectJ. SolutionThe flyweight pattern provides mechanisms by which fine-grained objects can be incorporated into an OO design without incurring a resource and performance penalty by sharing the objects where appropriate. A heavyweight object encapsulates the actual data to be referred to by potentially many flyweight objects. The abstract aspect in Example 18-3 uses the Director aspect-oriented design pattern (see Chapter 23) to provide a template by which application specific aspects can apply the flyweight pattern. Example 18-3. Using an abstract aspect to define the flyweight patternpublic abstract aspect FlyweightPattern { private Hashtable flyweightPool = new Hashtable( ); public interface Flyweight { }; protected abstract pointcut flyweightCreation(Object key); Object around(Object key) : flyweightCreation(key) && !within(com.oreilly.aspectjcookbook.oopatterns.FlyweightPattern+) { return this.checkFlyweight(key); } public synchronized Flyweight checkFlyweight(Object key) { if (flyweightPool.containsKey(key)) { return (Flyweight) flyweightPool.get(key); } else { Flyweight flyweight = createNewFlyweight(key); flyweightPool.put(key, flyweight); return flyweight; } } protected abstract Flyweight createNewFlyweight(Object key); } DiscussionFigure 18-5 shows the structure of the FlyweightPattern abstract aspect and the interfaces and behavior that it defines to support the flyweight design pattern. Figure 18-5. The FlyweightPattern aspect and the interfaces it defines for the design pattern's rolesThe abstract FlyweightPattern aspect in Example 18-3 contains a flyweight pool collection. This collection, implemented as a hash table, remembers the heavyweight objects that have already been created so flyweights can be set to the existing heavyweight objects where available. Because the abstract aspect does not know how to create the different concrete flyweight objects, it defines an abstract method createNewFlyweight(...). This abstract method allows subaspects to implement how they will create the specific flyweight objects. The FlyweightPattern aspect also contains the flyweightCreation(Object) abstract pointcut used to capture when objects, designated as flyweights, are being created. This pointcut enables the FlyweightPattern to override the creation of the flyweight objects using the associated around( ) advice to apply the design pattern's rules by checking whether an existing heavyweight object can be employed using the checkFlyweight(..) method, creating a new heavyweight object if necessary. The aspect in Example 18-4 shows how the abstract FlyweightPattern aspect can be applied for a specific application. Example 18-4. Applying the FlyweightPattern aspect to an application's classespublic aspect PrintableCharacterFlyweight extends FlyweightPattern { declare parents : PrintableCharacter implements Flyweight; protected pointcut flyweightCreation(Object key) : call(public com.oreilly.aspectjcookbook.PrintableCharacter. new(Character)) && args(key); protected Flyweight createNewFlyweight(Object key) { return new PrintableCharacter((Character) key); } } The PrintableCharacterFlyweight specifies that the PrintableCharacter class is to be managed as a flyweight. The flyweightCreation(..) pointcut is implemented to capture when the PrintableCharacter objects are created. The createNewFlyweight(Object) method is implemented to create new PrintableCharacter objects where necessary. Figure 18-6 shows the effects before and after the PrintableCharacterFlyweight aspect is applied to an application. Figure 18-6. The effects of applying the flyweight pattern to the PrintableCharacter classFigure 18-7 shows how the new flyweight behavior of the PrintableCharacter class behaves in an example application. Figure 18-7. Using the new flyweight behavior of the PrintableCharacter classSee AlsoFor more information on defining abstract aspects and specializing them, please refer to the recipes in Chapter 15; the Director aspect-oriented design pattern is explained in Recipe Recipe 23.3. |