Your question seems a bit circular to me...implementing an interface and having an instance of that interface that is "decorated" is the definition of the decorator pattern.
So your question is a bit like asking "Why does the decorator pattern use the decorator pattern?"
If there isn't a common interface between the thing you're wrapping and yourself, it's just a has-a relationship, or, if you're adapting the interface of the thing you're wrapping to some other interface, it might be the adapter pattern.
I think your real question is "Why is the decorator pattern useful? What makes it useful to implement the same interface as something you wrap?"
The Decorator Pattern Enables Variations on the Same Behavior
The greatest value of the decorator pattern comes when you have some system that must handle several subtly different things, but wants to not have to know about the complexity, and be able treat them all the same way. This is generally what we get from interfaces, of course. But in some cases, numerous implementations of the same interface are not the best solution...in the classic example, suppose you tried to write a separate class for every type of coffee that Starbucks serves.
You'll start out with the basics, but gradually find yourself either needing to write classes like VentiMochaChaiWhipWithCinnamonOnTop
. Each time a new flavor ingredient is added, you'd need to write dozens of new classes, and each time one is removed, dozens of classes would become obsolete.
With the decorator pattern, on the other hand, you can have what feels like a separate class for each drink, and enable large portions of the software system to not have to deal with the variety of drink types; they can treat each drink the same (no matter how many add-ons it has) through the Drink
interface.
You just make a new Chai()
when the person at the checkout hits the Chai button, and because the other attributes can be added to an arbitrary drink, you just wrap it with new Venti(drink)
, new Mocha(drink)
, new Whip(drink)
, new WithCinnamon(drink)
, etc. as the customer requests add-ons and the person at the register hits the buttons.
Limitations of the Decorator Pattern
The pattern has its limitations, since it's a bit harder to do introspection about what exact drink you have than, say, if you just used a set of booleans for each flavoring. I'm pretty sure it's not something that would actually be useful for keeping track of drink types in designing a cash register for Starbucks, because it wouldn't be very good at handling "Oops, I meant blackberry flavor, not raspberry"...supporting that in the decorator pattern would require introspection through several nested Drink decorators to find the Rasberry
decorator that needs to be removed.
It also isn't very good at handling things that have complicated inter-relationships...if the whipped topping needs to know what base drink type it's associated with to know whether it should add $.25 to the price or not, then the decorator pattern won't be very useful: the decorator pattern is for cases where the various decorations don't have to know about what exact implementation they're wrapping. When we can use it, it helps reduce coupling.
What I Really Find Useful
I think we use the drink example for explaining the decorator pattern mostly because it's very easy to talk about the potentially exponential savings in the number of classes that need to be created, while many real examples of where it's useful to decorate something don't actually use that property of the decorator pattern.
The cases that I can think of where something close to the pattern has been used at our company have been cases where we wanted to add some logging to a process. For example, by decorating an Eclipse IProgressMonitor, we can detect each time the displayed task or subtask name changes, and log how long each step of the process takes, so we know what steps are taking the most time.
Doing this as a decorator gives us the ability to access all that logging information without having to change much of our existing code (just the start-up of the job to be monitored), as it all knows how to handle an IProgressMonitor already, and we don't have to know what the progress monitor we wrap does internally either: we don't have to provide an alternative implementation, just wrap an existing implementation withe the additional behavior we want.