newbie
newbie

Reputation: 154

how to use decorator pattern to directly modify members of base class?

Base class A:

class A {
public:
    A() {}
    ~A() {}
    void methodOfA() { fill(array_.begin(), array_.end(), 100); }
private: 
    vector<int> array_;
};

Decorator class B:

class B: public A {
    A* a_;
public: 
    B(A* a) { a_ = a; }
    ~B() {}
    A* getA() { return a_; }
};

Now if I create an instance of B and use it like the following:

A a;
B b(&a);
b.methodOfA();

I want b to access or change everything that a has. To do that, one can use:

b.getA()->methodOfA();

This does not look good to me, is there any way to do something like:

b.methodOfA();

but achieve the same effect as b.getA()->methodOfA(); Note that A may not have a copy constructor to copy everything to B and I want everything done to b that happen in a.

To clarify: If I override every member functions of A (e.g. methodOfA()) in B, I can achieve what I want above. But there are about 50 functions in A to override. Is there any better solution?

Upvotes: 0

Views: 833

Answers (2)

Quentin
Quentin

Reputation: 63134

I see two solutions:

1 - Private inheritance

struct A {
    void stuff() {}
};

struct B : private A {
    using A::stuff;
};

int main() {
    B b;
    b.stuff(); // OK
}

You'll need to list all of A's methods, but you don't have to redefine anything.

2 - Operator overloading

struct A {
    void stuff() {}
};

struct B {

    A *operator -> () {
        return &a;
    }

    A a;
};

int main() {
    B b;
    b->stuff(); // Yuck. But OK.
}

On one hand, you can't have the b.stuff() syntax without implementing the stuff method in either B or one of its bases. On the other hand, overloading an operator may not be intuitive to user code. I guess you'll have to choose your poison.

Upvotes: 1

Mike Nakis
Mike Nakis

Reputation: 62015

First of all, A::methodOfA() needs to be virtual.

Then, in B, you need to add this:

virtual void methodOfA() { a_->methodOfA(); }

That's the decorator pattern.

Theoretically there could be a utility which, given a class, automatically generates a decorator for it, but I am not aware of any.

There is a number of things you can do to reduce the number of methods of A so as to make writing your decorator easier:

  1. Combine multiple methods which do not really need to be different into one. For example, raiseFlag() and lowerFlag() can become setFlag( bool flag ).

  2. Extract the public interface of A into a separate class I, and make both A and B extend I. Then, remove utility methods of A (methods implemented by invoking other methods of the same interface) put them in I, and make them non-virtual. So, you will have a reference to an I which implements some methods by itself, (invoking other methods on itself,) and this I will be implemented by an instance of B in which each virtual method delegates to (decorates) the corresponding virtual method of an instance of A.

Also, please note that the problem with implementing the decorator pattern by writing one decorator method for each method in the original interface is just a fact of life and irrelevant to elegance. In engineering, elegance is about avoiding hacks, not about saving keystrokes.

Upvotes: 2

Related Questions