Decorator Pattern: restrict wrapping
TL;DR: How to avoid duplicates for certain classes in a Decorator chain?
Long version
I'm trying to implement the Decorator pattern as described in the book Head First Design Patterns. The example they give is a cash register for a Starbucks-like coffee store, where the beverages and the various condiments are classes, and the purpose of the system is to calculate the price.I started with an iBeverage interface, exposing the public method getName() and getPrice().
Implementations of iBeverage are the various beverage classes (though a shared baseclass called Beverage; these are SlowDripCoffee, Latte and Cappuccino), and various condiments.
The condiments are implemented as iBeverageDecorators (an interface extending iBeverage). In their constructor they accept an instance of iBeverage, which is stored internally. Calls to getName() and getPrice() are implemented as "call getPrice() on child, add your own price, return the value."
Example of how one would create a Tall Soy Caramel Latte:
$drink = new SoyMilk(new CaramelSyrup(new Latte(Beverage::TALL)));
$price = $drink->getPrice();`
My issue: How can I restrict - for some decorators only - the total amount of times they end up in the call stack? For example: what if the store wants to restrict syrups to three per beverage, or they want to make sure employees only add one type of milk to an order?
My basic instinct was to add some reflection, so that during construction we can examine the entire object graph and determ开发者_JAVA百科ine whether or not it is a valid target for the decorator... is this the right way to go? Or is the pattern I'm applying here not suitable for this task? Any advice is much appreciated.
This is just something I set out for myself to do and find out.
Normally this should be an issue, you build your chain either manually (you hard coded it) or you have a builder that adds the decorators to the chain where you can control this.
I wouldn't put any code for this in the decorator classes itself because then you are spreading the rules about this all over the place and making this inflexible and hard to maintain.
The example you used is all about being able to cope with changed rules and ingredients.
精彩评论