As I understand, decorator is a pattern to "decorate" an object with... well, "decorations". What confused me is, why don't we just use a collection of "decorations" in the intended "decorated" object? why make things complicated with this decorator pattern? is there a downside with collection approach?
the most common example to demonstrate this pattern is pizza (object) and toppings (the decorations). I think it's a lot easier to just put collection of toppings inside pizza class, right? CMIIW.
Yeah, if I were implementing the pizza shop I might well use a list of toppings inside the Pizza object instead of using the Decorator pattern. But on the other hand there's more than one way to skin a cat. (No cats were harmed in the typing of this post.) And you have to admit it's not a bad example of the Decorator pattern, given that examples are often unrealistic and artificial.
Whether one version or the other is better is going to depend on the actual detailed requirements. For example you might implement a solution which breaks when the management decides to allow "Double Pepperoni" topping which doesn't cost twice as much as "Pepperoni" topping.
The decorator pattern allows you to "decorate" the objects in ways that were not foreseen when designing the object. If your boss decided to modify the pizza in a way which is not a topping (say, he wants you to cut ornamental patterns into it), you might need to modify the Pizza class to contain a list of topping and the pattern to cut. And then the boss decides to write poems on it.... (Obviously I shouldn't be allowed to run an Italian restaurant.)
Every decorator could be put inside of the object it decorates instead. But keeping the decorator outside helps to keep the classes small and let each class do one thing, and do it well. Good example are decorators in the Collection framework - you have a decorator to make a collection synchronized, or to make it read-only, or to let it accept only objects of certain class. Without decorators, you'd have to include code to support these modification in each collection implementation, and it would get pretty bloated quick.
David Spades wrote:but even with decorator, your double pepperoni scenario will break the code, right?
Possibly, but not necessarily.
The main difference as I see it is that "decoration" is an objective solution - ie, one that uses the power of constructs provided by the language - whereas a Collection is basically a procedure. Obviously, there are laws of diminishing return on any of this sort of stuff - I'm not sure I'd want to see an app littered with scads of Decorators, but they can be very useful when there's only a handful to deal with. And they also provide a platform for documentation.
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
It's been said between the lines here so sorry if it was already abundantly clear: the decorator pattern is for when you need to do more than just add a collection of some object to something. It's about the flexibility to add and modify behavior of an object through its decorations. A better example of the decorator pattern if you look is how streams have been implemented in Java. Check out this article because I think it will really help: Decorate your Java code
Here's a significant thing about the Decorator pizzas: it's possible that the data in the pizza shop is backed by a database which keeps track of the various toppings, including how much they cost and a lot of other things. A database-oriented design leads more or less directly to the idea that a pizza will include a list of toppings. And in this case adding a new kind of topping doesn't require any code changes, which may be an important feature to many people. Which is why I indirectly described the Decorator design as unrealistic and artificial. And I agree with Scott that there are better examples, such as the ones he linked to.
Another problem of the Decorator pizza design is that after you have written two or three Topping decorators, you might start noticing they all decorated the pizza with the same behaviour. You might then think that having a single Topping decorator with parameters was a better design. And a class with a single Decorator isn't much of a design; you still feel hungry for more. Perhaps a CrustType decorator? But then you're just taking an ordinary attribute and inflating it into a Decorator class. No, the real benefit of Decorators is when you have a number of Decorator classes which add value in significantly different ways.