1

I have to use the Decorator pattern, based on an UML diagram. Depending on the type of string I input, I have to return a price and a description. The issue I'm encountering is that the UML description strictly specifies that the price function is not virtual, and furthermore, it should only be implemented in the Smoothy interface, as shown below in the code:


#include<iostream>
using namespace std;

class Smoothy{
    int price;
public:
    int getPrice(){
        return price;
    }
    virtual ~Smoothy() = default;
    virtual string description() = 0;
};

class BasicSmoothy: public Smoothy{
private:
    string nume;
public:
    BasicSmoothy(string n): nume(n){}
    string description(){
        return nume;
    }
};

class SmoothyDecorator:public Smoothy{
private:
    Smoothy *b;

public:
    SmoothyDecorator(Smoothy* bb){
      b = bb;
    }
    ~SmoothyDecorator(){
        delete b;
    }
    string description(){
        return b->description();
    }
};

class SmoothyWithCream:public SmoothyDecorator{
public:
    SmoothyWithCream(Smoothy *b):SmoothyDecorator(b){

    }
    string description(){

        return SmoothyDecorator::description() + " with Cream!";
    }
};

class SmoothyWithCinnamon:public SmoothyDecorator{
public:
    SmoothyWithCinnamon(Smoothy *b):SmoothyDecorator(b){

    }
    string description(){
        return SmoothyDecorator::description() + " with Cinnamon!";

    }
};

int main(){
     Smoothy* b = new SmoothyWithCinnamon(new BasicSmoothy("Kiwi"));
     cout<<b->description();

}

I'm pretty sure my code reflects the Decorator pattern(plese let me know if it doesn't), but I'm not sure how to return the price, based on the string. In addition to that, the UML diagram specifies that the BasicSmoothy has two types, with two specific prices(Kiwi 10$, Strawberry 12$) and the Derived classes each add 2$ and 3$ to the final listed price.

Is there a way to return the price through the function getPrice() without it being virtual and without implementing it in the other classes?

  • What do you mean by "UML description"? In C++ the way to define an "interface" is to make the methods virtual. Are you looking for a technical solution to changing the price, or for a semantical discussion? – Tiberiu Maran Jul 10 '19 at 17:10
  • In addition to the UML diagram, there were a few bullet points that described function behaviors, one of them specified that the getPrice function is not virtual, sorry I wasn't clear enough! I'm looking for a technical solution. – bob_the_builder Jul 10 '19 at 17:15
  • If you are looking for a technical solution, you will need to provide more information on what you can change/touch. If you can change the base class, making the method virtual will allow you to use the decorator pattern freely. If you can't change the base class, it depends a lot on the reason why you can't change it, and most likely you will look for solutions outside the standard, that take "implementation" into account. – Tiberiu Maran Jul 10 '19 at 17:21
  • Unfortunately I can't change the base class. Just what the function does, so a solution outside of the standard is my only option unfortunately. – bob_the_builder Jul 10 '19 at 17:34
  • you can have a look at this: https://stackoverflow.com/a/19209874/4377932 – Tiberiu Maran Jul 12 '19 at 07:09

2 Answers2

1

You can make the price protected and overwrite it in the decorator:

#include<iostream>
using namespace std;

class Smoothy{
protected:
    int price;
public:
    int getPrice(){
        return price;
    }
    virtual ~Smoothy() = default;
    virtual string description() = 0;
};

class BasicSmoothy: public Smoothy{
private:
    string nume;
public:
    BasicSmoothy(string n): nume(n) {
        if (nume == "Kiwi") {
            price = 10;
        } else if (nume == "Strawberry") {
            price = 12;
        } else {
            throw;
        }
    }
    string description(){
        return nume;
    }
};

class SmoothyDecorator:public Smoothy{
private:
    Smoothy *b;

public:
    SmoothyDecorator(Smoothy* bb){
      b = bb;
    }
    ~SmoothyDecorator(){
        delete b;
    }
    string description(){
        return b->description();
    }
};

class SmoothyWithCream:public SmoothyDecorator{
public:
    SmoothyWithCream(Smoothy *b):SmoothyDecorator(b){
        price = b->getPrice() + 2;
    }
    string description(){

        return SmoothyDecorator::description() + " with Cream!";
    }
};

class SmoothyWithCinnamon:public SmoothyDecorator{
public:
    SmoothyWithCinnamon(Smoothy *b):SmoothyDecorator(b) {
        price = b->getPrice() + 3;
    }
    string description(){
        return SmoothyDecorator::description() + " with Cinnamon!";

    }
};

int main(){
    Smoothy* b = new SmoothyWithCinnamon(new BasicSmoothy("Kiwi"));
    cout<<b->description() << std::endl;
    cout << b->getPrice();
}
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
0

For anyone curios, I managed to find the solution.

class Smoothy
{

public:

    Smoothy()
    {

    }

    Smoothy(int n):
        price(n)
    {
    };

    virtual ~Smoothy() = default;

    int getPrice()
    {
        return price;
    }

    virtual string description() = 0;

private:

    int price;
};


class BasicSmoothy :
    public Smoothy
{
public:

    BasicSmoothy(string n) :
        Smoothy(n=="Kiwi"?10:12),
        nume(n)
    {
    }

    string description()
    {
        return nume;
    }

private:

    string nume;
};

class SmoothyDecorator :
    public Smoothy
{
public:

    SmoothyDecorator(Smoothy* bb, int pret) :
        Smoothy(pret + bb->getPrice()), b(bb)
    {

    }

    ~SmoothyDecorator()
    {
        delete b;
    }

    string description()
    {
        return b->description();
    }

private:

    Smoothy* b;
};

class SmoothyWithCream :
    public SmoothyDecorator
{
public:

    SmoothyWithCream(Smoothy* b) :
        SmoothyDecorator(b, 2)
    {
    }

    virtual string description()
    {
        return SmoothyDecorator::description() + " with Cream!" + to_string(getPrice());
    }
};

class SmoothyWithCinnamon :
    public SmoothyDecorator
{
public:

    SmoothyWithCinnamon(Smoothy* b) :
        SmoothyDecorator(b, 3)
    {
    }

    virtual string description()
    {
        return SmoothyDecorator::description() + " with Cinnamon!" + to_string(getPrice());
    }
};

int main()
{
    Smoothy* b1 = new SmoothyWithCinnamon(new SmoothyWithCream(new BasicSmoothy("Kiwi")));
    Smoothy* b2 = new SmoothyWithCinnamon(new SmoothyWithCream(new BasicSmoothy("Strawberry")));

    cout <<b1->description() << std::endl;
    cout <<b2->description() << std::endl;

    delete b1;
    delete b2;


}