• 文章
  • 使用模板裝飾物件
釋出
2011 年 6 月 25 日(上次更新:2011 年 6 月 25 日)

使用模板裝飾物件

得分:3.5/5 (64 票)
*****
裝飾器模式在 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 指標來工作,我們現在已經失去了在不進行向下轉換的情況下呼叫 d1d2 的能力。

但是,還有另一種方法。考慮以下模板:
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 類中的模板化建構函式將建構函式傳遞給派生類。