裝飾器模式在 Wikipedia 上解釋得相當清楚,但其原則是擁有一個公共基類,該基類的一些實現,以及修改這些實現的函式功能而不修改實現本身的需求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
struct CommonBase
{
virtual void func() =0;
};
struct Derived1 : public CommonBase
{
virtual void func() {
//implementation
}
void d1() {}
};
struct Derived2 : public CommonBase
{
virtual void func() {
//different implementation
}
void d2() {}
};
|
假設我們希望每次呼叫
func 都列印一條訊息。裝飾器模式表示我們可以這樣做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
struct Decorator : public CommonBase
{
CommonBase *b;
Decorator(CommonBase *b) : b(b) {}
virtual void func() {
std::cout << "Message" << std::endl;
b->func();
}
};
CommonBase *cb2 = new Decorator(new Derived2);
cb2->func();
CommonBase *cb1 = new Decorator(new Derived1);
cb1->func();
|
這很棒。但是,存在一個缺點,因為我們只能透過
CommonBase 指標來工作,我們現在已經失去了在不進行向下轉換的情況下呼叫
d1 和
d2 的能力。
但是,還有另一種方法。考慮以下模板:
1 2 3 4 5 6 7 8 9 10 11
|
template<class T>
struct DifferentDecorator : public T
{
virtual void func() {
std::cout << "Message" << std::endl;
T::func();
}
}
Derived1 *d1 = new DifferentDecorator<Derived1>;
Derived2 *d2 = new DifferentDecorator<Derived2>;
|
現在,我有一個可以處理任何提供
func 的類的單個裝飾器,因此我不需要複製程式碼。但是我現在可以使用指向派生類的指標來呼叫我想要的任何方法,因此不再侷限於
CommonBase 中的內容。
可以使用
BetterDecorator 類中的模板化建構函式將建構函式傳遞給派生類。