I am having difficulty understanding the following implementation advice from Erich Gamma's
book Design Patterns
regarding Decorator
pattern.
Omitting the abstract Decorator class There's no need to define an abstract Decorator class when you only need to add one responsibility.
I don't see why abstract Decorator class is required at all? Why can't all decorators simply implement/inherit directly IComponent/Component?
A decorator adds some functionality to some other classes. He forwards all messages for the old functionality to the decorated class. The new functionality is handled by the decorator itself. If there a more than one kind of new functionality to add than the code to forward the old functionality to the decorated class is placed in more than one class. That is why an abstract decorator is used.
Example:
In the example above we want to derocate some classes from the IComponent hierarchy with either functionality A oder functionality B. The forwarding code for "someFunctionality()" would be in both classes. So we extract an abstract decorator class (avoid duplication). The only code in the derived decorators is now the functionality to be added plus calling the method of the superclass. This is important, because if the logic of the forwarding changes you have to change only the superclasses method. You can decorate FirstDerived and SecondDerived with the functionality A or B.
If you want to decorate the existing classes with no more than one functionality, you don't have to extract the forwarding of "someFunctionality", because there is only one decorator where this forwarding code is placed in.
Example:
Gamma's implementation hint is about omitting the abstract decorator class which's only purpose is to forward the functionality of the ClassHierarchy so that in the concrete decorators is only the code that is important to add its new functionality.
I recommend you to start without the abstract decorator. But if you add a second decorator than you have to remove the duplicated code and thus extract the abstract class during your refactoring.
I don't see why abstract Decorator class is required at all? Why can't all decorators simply implement/inherit directly IComponent/Component?
The purpose of the abstract
class in the Decorator pattern is to eliminate code duplication. The crux of the Decorator pattern is to allow you to wrap an existing Component with new responsibilities. This wrapping is done by creating a new class that IS-A component and HAS-A component :
public class Decorator implements Component {
private Component component;
public Decorator(Component component) { this.component = component; }
}
Imagine that you introduce two more decorators. You would now have to implement similar code in both your new decorators. The abstract decorator can help you solve exactly this problem. By moving the above code to an abstract class, all your concrete decorators can inherit from it and avoid the need to re-implement the decorator skeleton manually.
I understand that the Decorator
in the above example doesn't do much; however, imagine a situation where you want to disallow further decoration based on some condition. For example, don't allow any more toppings on a Pizza if the cost will exceed 15$. The abstract decorator can take care of this by calling the getCost function on the component in the constructor. This will result in a call to all the getCost function of all the decorators and give you a final cost. If getCost()>15
, the application can inform the user that the cost cannot exceed 15$. Such code reuse is the real motivation behind the abstract decorator class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With