Java Reference
In-Depth Information
You must add the decorators to the
bean.xml
archive in the order that you want them to be invoked.
Here, you declare that the
PriceDiscountDecorator
decorator should be invoked before the
BlackFridayDiscountDecorator
decorator.
<decorators>
<class>com.devchronicles.decorator.PriceDiscountDecorator</class>
<class>
com.devchronicles.decorator.BlackFridayDiscountDecorator
</class>
</decorators>
When the
generateLabel
method is invoked, a call chain is set up that includes the two
decorators. The call to
generateLabel
is intercepted and delegated to the
generateLabel
method
of the
PriceDiscountDecorator
. It calls
r getPrice
, which will be intercepted and delegated to
the
getPrice
method of
BlackFridayDiscountDecorator,
which in turn calls the
getPrice
method of its injected
Product
object. (This is the same instance that you injected into the
PriceDiscountDecorator
decorator.) This invocation is not intercepted because there are no
more decorators declared for this interface, and it calls the
getPrice
method in the
Table
object.
Once this call has i nished, it returns down the call stack to the i rst
getPrice
method. This is
called returning the price of the
Table
. The decorator reduces the price by 50 percent and calls the
setPrice
method. This call is delegated up the call chain until it reaches the
Table
object, where the
new price is set. Then the call returns down the call chain.
The
getLabel
method is called and creates a call chain similar to that of the
getPrice
method.
Finally, the
generateLabel
method is invoked and intercepted by the
BlackFridayDiscountDecorator
decorator. The price is discounted by a further 25 percent, and a
call chain similar to that set up by the
PriceDiscountDecorator
decorator is initiated.
The output to the console follows:
Label: 6.25, Dining Table (Discounted)
For the chain to continue unbroken, the
generateLabel
method must delegate to the
generateLabel
method of the delegate injected instance; otherwise, the chain is broken and only
the i rst decorator is invoked.
All classes that implement the same interface as the one implemented by the delegate injection
point are decorated, but only if those decorators are declared in
bean.xml
. This has two major
implications:
➤
Decorators can be enabled and disabled at deployment time by editing the
bean.xml
i le.
This gives great l exibility over when and which decorators are invoked. For example, you
can implement a price discount decorator only for the duration of the sales period and
disable it when the period comes to an end. The l exibility of the deployment descriptor
declaration means that this decorator can be easily enabled again if debugging information is
later required.
➤
A decorator is automatically applied to classes that implement the same interface. This is
efi cient at the time of adding new classes because they are decorated with no additional
coding. However, this could prove inconvenient if there is a requirement that not all classes
of the same type are decorated. Luckily, there is a solution to this situation that involves
using qualii ers to annotate only those classes that should be decorated.