基类A:
class A {
public:
A() {}
~A() {}
void methodOfA() { fill(array_.begin(), array_.end(), 100); }
private:
vector<int> array_;
};
装饰等级B:
class B: public A {
A* a_;
public:
B(A* a) { a_ = a; }
~B() {}
A* getA() { return a_; }
};
现在,如果我创建一个B的实例并像下面这样使用它:
A a;
B b(&a);
b.methodOfA();
我希望b访问或更改a所拥有的一切。要做到这一点,可以使用:
b.getA()->methodOfA();
这在我看来不太好,有什么方法可以做这样的事情吗:
b.methodOfA();
但达到了与b.getA()->methodOfA()相同的效果;请注意,A可能没有复制构造函数来将所有内容复制到B,我希望在A中发生的所有内容都复制到B。
澄清:如果我在B中重写A的每个成员函数(例如methodOfA()),我就可以实现上面想要的。但是A中大约有50个函数需要重写。有更好的解决方案吗?
首先,A::methodOfA()
需要是虚拟的。
然后,在B中,您需要添加以下内容:
virtual void methodOfA() { a_->methodOfA(); }
这就是装饰器模式。
理论上,给定一个类,可能会有一个实用程序自动为它生成一个装饰器,但我不知道有什么。
可以做很多事情来减少A
的方法数量,从而使编写装饰器变得更容易:
将多个不需要真正不同的方法组合为一个。例如,
raiseFlag()
和lowerFlag()
可以变成setFlag( bool flag )
。将
A
的公共接口提取到一个单独的类I
中,并使A
和B
都扩展了I
。然后,移除A
的实用方法(通过调用同一接口的其他方法实现的方法),将它们放在I
中,并使它们成为非虚拟的。因此,您将有一个对I
的引用,它自己实现了一些方法(在自己身上调用其他方法),而这个I
将由B
的实例实现,其中每个虚拟方法都委托(装饰)A
实例的相应虚拟方法。
此外,请注意,通过为原始接口中的每个方法编写一个decorator方法来实现decorator模式的问题只是生活中的一个事实,与优雅无关。在工程中,优雅是为了避免黑客攻击,而不是为了保存击键。
我看到了两种解决方案:
1-私有继承
struct A {
void stuff() {}
};
struct B : private A {
using A::stuff;
};
int main() {
B b;
b.stuff(); // OK
}
您需要列出A
的所有方法,但不必重新定义任何内容。
2-操作员过载
struct A {
void stuff() {}
};
struct B {
A *operator -> () {
return &a;
}
A a;
};
int main() {
B b;
b->stuff(); // Yuck. But OK.
}
一方面,如果不在B
或它的一个基中实现stuff
方法,就无法获得b.stuff()
语法。另一方面,重载运算符对用户代码来说可能不是直观的。我想你必须选择你的毒药。