1

例子:

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 具体类中添加一个额外的装饰器。所以 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 ... */
}

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

4

2 回答 2

1

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

于 2012-06-29T06:33:08.260 回答
0

当然,为什么不呢?您实际上是在对您添加的装饰器进行专门化,或者是用于构造常用装饰器组合的实用程序类/方法。

听起来像是一个很好的代码整合。继续前进。

于 2012-06-29T06:45:54.427 回答