Most of you know the pizza / cofee example for the decorator pattern.
Pizza* pizza1 = BigPizzaDecorator(MushromDecorator(SimplePizza()));
Pizza* pizza2 = MushromDecorator(BigPizzaDecorator(SimplePizza()));
the two object behave in a similar way, but not completely, in particular if you have non-commutative operation, for example:
BigPizzaDecorator::price() { return 10 + PizzaDecorator::price(); } // this is commutative
BigPizzaDecorator::name() { return "big " + PizzaDecorator::name(); } // this is not commutative
So the price for pizza1 and pizza2 are the same, but the name is not, for example the first should be "Big mushroom pizza", the second "Mushroom big pizza". The first is english correct (probably better would be “Big pizza with mushroom”, but it’s not so important).
The book “Head first” point out this problem with the Cofee example:
When you need to peek at multiple layers into the decorator chain, you
are starting to push the decorator beyond its true intent.Nevertheless, such things are possible. Imagine a CondimentPrettyPrint
decorator that parses the final decription and can print “Mocha, Whip,
Mocha” as “Whip, Double Mocha.”
what is the best way to do that? (operator< ?)
Ive never known this sort of thing to be needed when using decorators. And I would think that if you need to do this, then you shouldn’t be using decorators, especially as you’re knowingly “pushing the decorator beyond it’s intent”.
I have had a stab at doing this, the code is below. Basically, I create a thin layer around the
SimplePizzaobject that understands what the decorators need, then the decorators decorate that.The main problem here, is that to maintain order in the output, you would have to maintain a relationship between decorators – which can quickly become a maintenance nightmare.