装饰者模式:分离责任

时间:2017-01-26 12:28:06

标签: c++ design-patterns decorator

对于Decorator设计模式,GoF明确指出:

  

使用装饰器,可以在运行时添加和删除职责   只需将它们连接和拆卸即可。

我正在尝试用C ++构建一个框架代码,我可以很容易地看到这个模式如何为未修饰的对象添加职责。

我的问题是如何删除特定的责任。删除最后包装的责任可以轻松完成。但我是否也可以删除之间添加的责任。

以下是我的示例代码:

class Icecream { //Component
    public :
    virtual void addToppings() = 0 ;
    virtual Icecream *getUndecorated() = 0 ;
} ;
class PlainIcecream : public Icecream { //Concrete Component
    public :
    void addToppings() { cout<<"I am just plain icecream, you may add more flavors\n" ; }
    Icecream * getUndecorated() {return this ; }
} ;
class Topping : public Icecream { //Decorator
    protected :
    Icecream *icecream ;
    public :
    Topping(Icecream *i) : icecream(i) {}
    void addToppings() { icecream->addToppings() ; }
} ; 
class PeanutToppings : public Topping { //Concrete Component A
    public :
    PeanutToppings(Icecream *i) : Topping(i) {}
    void addToppings() {
        Topping::addToppings() ;
        cout<<"Adding peanut toppings for great taste\n" ; 
    }
    Icecream * getUndecorated() {return icecream ; }
} ;
class CandyToppings : public Topping { //Concrete Component A
    public :
    CandyToppings(Icecream *i) : Topping(i) {}
    void addToppings() {
        Topping::addToppings() ;
        cout<<"Adding candy toppings for yummy flavour\n" ;
    }
    Icecream * getUndecorated() {return icecream ; }
} ;
main() {
    Icecream *icecream_with_candy_and_peanuts = new CandyToppings(new PeanutToppings(new PlainIcecream)) ;
    icecream_with_candy_and_peanuts->addToppings() ;
    cout<<"_________________________________________________\n" ;
    Icecream *icecream_with_only_peanuts = icecream_with_candy_and_peanuts->getUndecorated() ;
    icecream_with_only_peanuts->addToppings() ;
    cout<<"_________________________________________________\n" ;
    Icecream *icecream_plain = icecream_with_only_peanuts->getUndecorated() ;
    icecream_plain->addToppings() ;
}

现在我想知道是否有可能只有来自icecream_with_candy_and_peanuts的糖果的冰淇淋。请不要考虑我为什么要这样做。我只是想了解这个词

  

分离职责

如GoF所述。

1 个答案:

答案 0 :(得分:2)

  

可以轻松删除最后包装的责任

无需单独的getUndecorated方法。这不是标准 Decorator 模式定义的一部分。

  

现在我想知道是否可以制作一个冰淇淋,只有来自icecream_with_candy_and_peanuts的糖果顶部

是的,你可以。当涉及到装饰器模式时,附加分离职责之间没有太大区别。要分离责任,您只需要重新创建组件:

//attaching responsibilities
Icecream *icecream = new new PlainIcecream();
*icecream = new PeanutToppings(icecream);//wrap around with new respnsibility
*icecream = new CandyToppings(icecream);//wrap around with new responsiblity

//detaching responsibilities
*icecream = new CandyToppings(new PlainIcecream());

注意我在两种情况下如何使用*icecream。您可以通过限制到单个界面(即IceCream)来附加分离职责。这就是 Decorator 模式背后的想法。

也就是说,使用HashMap(其中键是顶部名称)实现的 Composite 模式在您希望能够任意添加或者任意添加的情况下是更好的选择。从现有实例中删除职责。

额外提示:装饰器模式中的装饰器理想情况下不应该是可实例化的(在您的情况下为Toppings)。将Toppings重命名为ToppingsDecorator也会有所帮助。 (我知道这不是你要问的直接问题。这纯粹是为了其他读者的利益)