• 文章
  • 使用模板装饰对象
发布
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 类中的模板化构造函数将构造函数传递给派生类。