【问题标题】:Decorator pattern : Detaching responsibilities装饰者模式:分离职责
【发布时间】:2017-06-11 22:11:14
【问题描述】:

对于装饰器设计模式,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 中所述。

【问题讨论】:

  • 您的设计似乎有缺陷,因为浇头并不是真正的冰淇淋。请记住,继承是一种“是”关系。
  • @一些程序员老兄,您可以将它们视为基类,派生类。我已经提到过,关注点不是类名,关注点是从 GoF 中提到的装饰对象中分离责任。您可以根据需要命名这些类
  • @一些程序员老兄,我想让你考虑的是骨架,类名在这里根本没有意义
  • @user3282758 好问题。我以前从未使用过 Decorator 模式来 detach 职责,但这绝对是该模式的有效用例。请参阅我的答案以获得解释。

标签: c++ design-patterns decorator


【解决方案1】:

删除最后一个包装的责任很容易

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

现在我想知道是否有可能只用来自 icecream_with_candy_and_peanuts 的糖果来制作冰淇淋

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

//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(其中 key 是顶部名称)实现的 Composite 模式在您希望能够任意添加或删除职责的情况下是更好的选择从现有实例。

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

【讨论】:

  • 你的答案写得很好。但是我还有一个查询,就是你正在创建一个新实例,并用同一个指针引用这个新实例。这是否意味着icecream指针引用的原始对象不能减少责任
  • @user3282758 装饰器模式背后的想法是包装一个有责任的对象。要做到这一点包装,您需要创建一个新实例,围绕旧实例包装新职责(无论您是attaching 还是分离责任)你不清楚的原因是因为你一步附加责任。请参阅我的编辑,我们将责任附加分离到原始`*icecream*。请注意,我的 C++ 生锈了,所以我的答案在语法上可能不正确。请随时编辑答案并删除错误
  • @user3282758 Composite 模式可能是这个用例的更好选择。见编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 2021-07-21
  • 2019-05-11
  • 2022-01-10
  • 2014-05-25
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多