简体   繁体   中英

Decorator Pattern : Why do we need an abstract decorator?

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.

I had the same doubt and I went through several articles for this , one of the additional points that i found is as below:

As per the Gang of Four we can have decorators without a need to extend an abstract class, puts only if we don't have many decorators for an object.

Why we shoud have abstract class then

Many times if we have multiple decorator implementations it may not be required to implement all the methods, but if every decorator implements the interface (IComponent) in your case,each and every decorator will be forced to implement methods which they might not need to implement.Given that your interface has many methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM