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

时间:2015-02-13 11:33:32

标签: c++ 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访问或更改所有内容。要做到这一点,可以使用:

b.getA()->methodOfA();

对我来说这看起来不太好,有什么方法可以做这样的事情:

b.methodOfA();

但实现与b.getA() - &gt; methodOfA();相同的效果;请注意,A可能没有复制构造函数来将所有内容复制到B,并且我希望在a中完成所有操作。

澄清: 如果我覆盖B中的A的每个成员函数(例如methodOfA()),我可以实现上面想要的。但是A中有大约50个函数要覆盖。有没有更好的解决方案?

2 个答案:

答案 0 :(得分:1)

首先,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每个虚方法委托(装饰){{1}}实例的相应虚方法。

  3. 另外,请注意,通过为原始界面中的每个方法编写一个装饰器方法来实现装饰器模式的问题只是生活中的事实,与优雅无关。在工程方面,优雅就是避免黑客攻击,而不是节省击键。

答案 1 :(得分:1)

我看到两个解决方案:

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()或其中一个基础中实施stuff方法,则无法使用B语法。另一方面,重载操作符可能对用户代码不直观。我想你必须选择你的毒药。