示例:
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)中使抽象基类指针受保护而不是私有,然后在具体的装饰器对象中添加额外的装饰器,就像我在示例中所做的那样,但这看起来像一个坏主意,因为它打破了数据封装,现在装饰者可能不正确地与他们装饰的对象进行交互。话虽如此,这是我唯一的选择吗?有没有更好的方法从具体的装饰器的“装饰”功能中包装复合装饰器与另一个装饰器,然后像往常一样继续?
答案 0 :(得分:1)
这就是事情。客户端应该知道要应用哪些装饰器。将此逻辑推送到内部装饰器是没有意义的,因为当客户端调用BorderDecorator时,它只期望边框而不是带滑块的边框。在客户端代码中,如果要链接多个需要动态指定的装饰器,可以使用Chain of Responsibility模式。
答案 1 :(得分:0)
当然,为什么不呢?您基本上将对您添加的装饰器进行专门化,或者使用实用程序类/方法来构建常用的装饰器组合。
听起来像是一个很好的代码整合。马上走吧。