prestokeys
prestokeys

Reputation: 4849

Is the Decorator Pattern a suitable choice here?

Consider the code below. Through A::doit(), a B object is supposed to increase total by 3. A Decorated1 object is supposed to increase total by 4, and a Decorated2 object is supposed to increase total by 5. An A object that is a combination of these derived types shall still carry out their "special actions" but is to increase total by the max (not sum) of the individual increases in total. But the decorator pattern is obtaining the sum instead of the max. Do I have to abandon the Decorator Pattern here?

#include <iostream>

int total = 0;

struct A {
public:
    virtual void doIt() = 0;
};

struct Decorator : public A {
    A* a;
    Decorator (A* a_) : a(a_) {}
    virtual void doIt() override {a->doIt();}
};

struct B : public A {
    virtual void doIt() override {
        total += 3;
        std::cout << "Special actions by B carried out.\n";
    }
};

struct Decorated1 : public Decorator {
    using Decorator::Decorator;
    virtual void doIt() override {
        Decorator::doIt();
        total += 4;
        std::cout << "Special actions by Decorated1 carried out.\n";
    }
};

struct Decorated2 : public Decorator {
    using Decorator::Decorator;
    virtual void doIt() override {
        Decorator::doIt();
        total += 5;
        std::cout << "Special actions by Decorated2 carried out.\n";
    }
};

int main() {
    A* decorated1_2 = new Decorated2(new Decorated1(new B));
    decorated1_2->doIt();
    std::cout << "total = " << total << std::endl;
}

Output:

Special actions by B carried out.  // Good I want this.
Special actions by Decorated1 carried out.  // Good I want this.
Special actions by Decorated2 carried out.  // Good I want this.
total = 12  // No, it is supposed to be 5, not the sum 3+4+5.

Upvotes: 4

Views: 170

Answers (2)

b4hand
b4hand

Reputation: 9770

You'll need to split the functionality of doIt up. You can't apply an increment in the function and do something special and not have both operations happen.

There's two ways you could accomplish this. Both require you to isolate the increment to its own method.

  • Make the increment value a polymorphic property and apply the increment in the base class and don't call the super class.
  • Fully override the increment in just the derived classes

Upvotes: 2

Pavan Sokke Nagaraj
Pavan Sokke Nagaraj

Reputation: 2435

Decorator pattern is a class of structural pattern, i.e structural patterns help you to add and build functionality to the current features

That's the reason you are getting the sum of all the decorators as 12 (B feature<<3>> + Decorated1 feature<<4>> + Decorated2 feature<<5>> ).

If you want to keep working on structural pattern and if you want to yield the expected results, you have to initialize and send object of class A to all the decorator classes separately..

Else, you can work on Strategy Design Pattern and get the same results..

One more good option would be to use Creational design patterns

You can check these examples about design patterns with java code over here.. https://github.com/pavansn/java-design-patterns

Hope it helps

Upvotes: 3

Related Questions