例子:
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)中使抽象基类指针受保护而不是私有,然后就像我在示例中所做的那样从具体的装饰器对象中添加额外的装饰器,但这看起来像一个坏主意,因为它破坏了数据封装,现在装饰器可能不正确地与它们装饰的对象交互。话虽如此,这是我唯一的选择吗?在具体装饰器的“装饰”功能中是否有更好的方法来用另一个装饰器包装复合装饰器,然后像往常一样继续?