例:
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を追加したいとします。したがって、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を適用したいだけであることも知っています。頭のてっぺんから、(私が取り組んでいるもの以外に)コンクリートデコレータオブジェクト内からデコレータを追加する必要がある理由の良い例を思い付くことができませんが、我慢してください。私にはそうする正当な理由があります。また、抽象デコレータオブジェクト(この例ではm_display)の抽象基本クラスポインタをプライベートではなく保護し、例のように具体的なデコレータオブジェクト内からデコレータを追加できることも知っていますが、これは次のようになります。データのカプセル化が崩れるため、悪い考えです。デコレータは、デコレートするオブジェクトと不適切に相互作用する可能性があります。そうは言っても、それが私の唯一の選択肢ですか?コンクリートデコレータの「デコレーション」機能内から、複合デコレータを別のデコレータでラップして、通常のように続行するためのより良い方法はありますか?