Design Patterns and Decorator : Pizza store

Jun 6, 2011 at 11:51am
Hello

I need to use Design Patterns with Decorator in order to implement a Pizza delivery (or Pizza store,just
the same) . I have the regular Pizza with no additions , meaning , this is the most basic order that
every client is entitled to. From here, every client can have 15 different additions to the pizza .
The problem is the client can have the same addition , any number of times that he wishes .

1
2
3
4
5
6
class Pizza {
public:
	Pizza();
	virtual ~Pizza();
	virtual double getCost() = 0;
};


1
2
3
4
5
6
7
8
9
10
11
class PizzaDecorator :public Pizza{
private:
	Pizza *m_wrappee;
protected:
	PizzaDecorator() {};
	PizzaDecorator(Pizza *inner) {this->m_wrappee = inner;}
public:

	~PizzaDecorator() {delete this->m_wrappee;};
	double getCost() {return this->m_wrappee->getCost();}
};



1
2
3
4
5
6
7
8
class RegularPizza :public Pizza {
private:
	double m_cost;
public:
	RegularPizza() {this->m_cost = 25;}
	~RegularPizza() {};
	double getCost() {return this->m_cost;}
};



1
2
3
4
5
6
7
8
9
10
11
class Mozzarella : public PizzaDecorator{

private:
	double m_cost;

public:
	Mozzarella(Pizza * core) : PizzaDecorator(core) { this->m_cost = 5;}
	Mozzarella();
	~Mozzarella();
	double getCost() { return (PizzaDecorator::getCost() + m_cost);}
};



Main.cpp
1
2
Pizza *regularPizza = new RegularPizza();
Pizza *pizzaWithMozzarella = new Mozzarella (new RegularPizza);


My questions are :
1. is this Decorator answers the requirements of "being a decorator" for the pizza ?
2. how can I add Mozzarella 10 times for some client ?

Thank you
Last edited on Jun 6, 2011 at 12:29pm
Jun 6, 2011 at 4:14pm
1) Looks good to me, your only problem that I can see is memory management.

I would also have made m_wrappee protected, and not bothered with the m_cost variables (just use the value directly in getCost), but that's just me.

2) With a loop

1
2
Pizza *pizza = new RegularPizza;
for(int i=0;i!=10;++i) pizza = new Mozzarella(pizza);


Jun 6, 2011 at 6:21pm
I don't like it. :-(

To me, a Pizza ingredient (decorator here) is not a pizza. Why is then PizzaDecorator inheriting from pizza? It is a no-no to me.

Each pizza should have an Ingredients collection. You can base your new collection on a vector<> or use the vector directly.

Each ingredient should know its own price, and therefore it is just a matter of adding up the prices of individual ingredients to obtain the prize of the pizza. Note, however, that basic pizzas have a defined set of ingredients and those ingredients should not count towards increasing the pizza's value.
Jun 6, 2011 at 7:47pm
@webJose: I think you need to read up on the Decorator pattern.
Jun 6, 2011 at 7:52pm
. I just read the entire post. I don't get the meaning of a decorator here from looking at the class the OP posted. Clearly the decorator inherits from pizza but gains nothing out of it. It instead uses a pizza by containment. So what's the gain from inheriting from Pizza????

Maybe I don't get it because I don't understand what a decorator is supposed to be. Is this an OOP concept? I'll look it up as I have never heard about it...
Jun 6, 2011 at 8:01pm
I see now. Clearly pizza is not a very good example to implement this pattern.

More appropriate decorators for pizza would be BoxedPizza, PlatedPizza, SlicedPizza. Example:

1
2
3
4
5
6
7
8
9
10
11
12
class SlicedPizza : public Pizza
{
    Pizza *m_pizza;
    int m_countSlices;

public:
    SlicedPizza(Pizza *pizza, int slices) : m_pizza(pizza), m_countSlices(slices), Pizza()
    { }

    int SlicesCount() const { return m_countSlices; }
    //Skipping overrides and such....
};


Surely to stack two of these make no sense, but you could take a pizza, slice it and then plate it or box it, satisfying the requirement.

I think I just have a problem with the ingredients. It is not natural to me.
Jun 7, 2011 at 10:34am

kev82 and webJose ,first of all thank you for the response.

Second,I have 15 different toppings (Mozzarella is only one of them to the pizza.
Now ,the thing is that I probably would have to use either 15 classes (and 15 .h and .cpp files) for
those toppings , or , use a Template in a single .h file , that would duplicate it self to the
appropriate topping (depends on the user's choice) . What do you think,Template or 15 classes upfront ?

Thanks again !!
Jun 7, 2011 at 11:25am
You don't need multiple header and implementation files. You can put multiple classes in the one file.

If you were to do it with templates, what would the template argument(s) be?

For me it depends very much on exactly what behaviour you are overloading in Pizza. If it is purely cost, then I don't see a reason why you can't use templates and/or macros to generate the class definitions for you.
Jun 7, 2011 at 1:56pm
I agree wtih kev82. A simple template could be:

1
2
3
4
5
6
7
8
9
10
11
template<const char *IngredientName, double price>
class IngredientDecorator : public Pizza
{
    const char *m_name;
    const double m_additionalPrice;

public:
    IngredientDecorator() : m_name(IngredientName), m_additionalPrice(price), Pizza()
    { }
...
}


Then you spawn all of your types with typedef's:

1
2
3
typedef IngredientDecorator<"Mozzarella", 0.50> MozzarellaDecorator;
typedef IngredientDecorator<"Pepperoni", 0.50> PepperoniDecorator;
....


DISCLAIMER: I have never used a template with a constant string before, so unsure if it works, although I don't see why it shouldn't work.
Last edited on Jun 7, 2011 at 1:56pm
Topic archived. No new replies allowed.