如何使用decorator模式直接修改基类的成员



基类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的方法数量,从而使编写装饰器变得更容易:

  1. 将多个不需要真正不同的方法组合为一个。例如,raiseFlag()lowerFlag()可以变成setFlag( bool flag )

  2. A的公共接口提取到一个单独的类I中,并使AB都扩展了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()语法。另一方面,重载运算符对用户代码来说可能不是直观的。我想你必须选择你的毒药。

最新更新