Пример:
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 ... */
}
Я также знаю, что в случае с этим примером я просто хотел бы применить SliderDecorator из клиентской функции (в данном случае main). Внезапно я не могу придумать хороший пример того, почему нужно добавлять дополнительные декораторы из конкретных объектов декораторов (помимо того, над чем я работаю), но терпите меня; У меня есть для этого веская причина. Я также знаю, что могу сделать абстрактный указатель базового класса в абстрактном объекте декоратора (m_display в этом примере) защищенным, а не закрытым, а затем добавить дополнительные декораторы из конкретного объекта декоратора, как я сделал в примере, но это похоже на плохая идея, поскольку она нарушает инкапсуляцию данных, и теперь декораторы могут неправильно взаимодействовать с объектами, которые они украшают. При этом, это мой единственный вариант здесь? Есть ли лучший способ из функции «украшения» конкретного декоратора обернуть композитный декоратор другим декоратором, а затем продолжить как обычно?
new SlideDecorator(new BorderDecorator(new PageDisplay())))? Или я не понял вашего вопроса... - person Jaime   schedule 29.06.2012