使用装饰器模式时,我可以在具体的装饰器对象中添加新的装饰器吗?

时间:2012-06-28 21:47:30

标签: c++ design-patterns decorator encapsulation

示例:

class Display
{
public:
    virtual void display() = 0;
};

class PageDisplay : public Display
{
public:
    void display() { /* ... */ }
};

class DisplayDecorator : public Display
{
public:
    DisplayDecorator(Display* display) : m_display(display) {}
    virtual void display() { m_display->display(); }
private:
    Display* m_display;
};

class BorderDecorator : public DisplayDecorator
{
public:
    BorderDecorator(Display* display) : DisplayDecorator(display) {}
    virtual void display() { DisplayDecorator::display(); /* do border stuff here ... */ }
};

int main()
{
    Display* pageDisp = new BorderDecorator(new PageDisplay());
    pageDisp->display();
}

所以,这是装饰模式的一个相当基本的实现。但是,比方说,我想在BorderDecorator具体类中添加一个额外的装饰器FROM WITHIN。所以BorderDecorator :: display函数现在看起来像这样:

virtual void display()
{ 
    /*
    I need to add a decorator that will display a slider bar at the side of the screen, 
    and that will wrap the PageDisplay decorator so that it will run before the page display.
    Is there a clean way to get my base class' m_display pointer so that I can do something like this:
    */
    m_display = new SliderDecorator(m_display);

    DisplayDecorator::display();
    /* do border stuff here ... */
}

我也知道在这个例子的情况下,我真的只想在客户端函数中应用SliderDecorator(在本例中为main)。在我的脑海中,我无法想出一个很好的例子,说明为什么人们需要在具体的装饰器对象中添加额外的装饰器(除了我正在处理的东西),但是我裸露;我有充分的理由这样做。我也知道我可以在抽象装饰器对象(本例中为m_display)中使抽象基类指针受保护而不是私有,然后在具体的装饰器对象中添加额外的装饰器,就像我在示例中所做的那样,但这看起来像一个坏主意,因为它打破了数据封装,现在装饰者可能不正确地与他们装饰的对象进行交互。话虽如此,这是我唯一的选择吗?有没有更好的方法从具体的装饰器的“装饰”功能中包装复合装饰器与另一个装饰器,然后像往常一样继续?

2 个答案:

答案 0 :(得分:1)

这就是事情。客户端应该知道要应用哪些装饰器。将此逻辑推送到内部装饰器是没有意义的,因为当客户端调用BorderDecorator时,它只期望边框而不是带滑块的边框。在客户端代码中,如果要链接多个需要动态指定的装饰器,可以使用Chain of Responsibility模式。

答案 1 :(得分:0)

当然,为什么不呢?您基本上将对您添加的装饰器进行专门化,或者使用实用程序类/方法来构建常用的装饰器组合。

听起来像是一个很好的代码整合。马上走吧。