Recipe 23.1. Applying the Cuckoo's Egg Design PatternProblemYou want to override the type of object instantiated on a constructor call to return an object of a different class transparently to the original business logic. SolutionApply the Cuckoo's Egg aspect-oriented design pattern. Figure 23-1 shows the key components of the Cuckoo's Egg pattern. Figure 23-1. The structure of the Cuckoo's Egg patternThe key roles in the Cuckoo's Egg pattern shown in Figure 23-1 are:
DiscussionAs simple as the Cuckoo's Egg pattern is, it is one of the more powerful capabilities of aspect orientation as implemented in AspectJ. It is reasonably common to want to control and change an object instantiated on a constructor call or on a factory method when an aspect is applied. The Cuckoo's Egg design pattern formalizes this common AspectJ use case. Example 23-1 is modified from Recipe 20.2 and shows how the Cuckoo's Egg pattern can be implemented in AspectJ to return an instance of AnotherClass when a MyClass constructor is called. Example 23-1. An example of the Cuckoo's Egg design patternpublic aspect ControlClassSelectionAspect // Cuckoo's Egg Aspect { public pointcut myClassConstructor( ) : call(MyClass.new( )); Object around( ) : myClassConstructor( ) { return new AnotherClass( ); } } The key characteristics of the Cuckoo's Egg pattern are:
The Cuckoo's Egg pattern is useful in circumstances where you do the following:
The Cuckoo's Egg pattern can collaborate with the Border Controller design pattern, which can be used to limit the constructor calls to a particular class overridden by the Cuckoo's Egg pattern. See AlsoThe article at http://www.onjava.com/pub/a/onjava/2004/10/20springaop2.html shows how to implement the Cuckoo's Egg Pattern using the Spring Framework; using the call(Signature) pointcut to capture and override a call to a constructor is described in Recipes Recipe 7.1 and Recipe 20.1; the around( ) form of advice is covered in Recipe Recipe 13.4; the AspectJ rules on how overriding around( ) advice can be applied are covered in more detail in Recipe Recipe 20.2. |