bob_the_builder
bob_the_builder

Reputation: 119

How to create a decorator function without using virtual

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?

Upvotes: 1

Views: 78

Answers (2)

bob_the_builder
bob_the_builder

Reputation: 119

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;


}

Upvotes: 0

Thomas Sablik
Thomas Sablik

Reputation: 16445

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();
}

Upvotes: 1

Related Questions