装饰器模式在 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 类中的模板化构造函数将构造函数传递给派生类。