views:

234

answers:

5

This question was asked already here, but rather than answering the specific question, descriptions of how the decorator pattern works were given instead. I'd like to ask it again because the answer is not immediately evident to me just by reading how the decorator pattern works (I've read the wikipedia article and the section in the book Head First Design Patterns).

Basically, I want to know why an abstract decorator class must be created which implements (or extends) some interface (or abstract class). Why can't all the new "decorated classes" simply implement (or extend) the base abstract object themselves (instead of extending the abstract decorator class)?

To make this more concrete I'll use the example from the design patterns book dealing with coffee beverages:

  • There is an abstract component class called Beverage
  • Simple beverage types such as HouseBlend simply extend Beverage
  • To decorate beverage, an abstract CondimentDecorator class is created which extends Beverage and has an instance of Beverage
  • Say we want to add a "milk" condiment, a class Milk is created which extends CondimentDecorator

I'd like to understand why we needed the CondimentDecorator class and why the class Milk couldn't have simply extended the Beverage class itself and been passed an instance of Beverage in its constructor.

Hopefully this is clear...if not I'd simply like to know why is the abstract decorator class necessary for this pattern? Thanks.

Edit: I tried to implement this, omitting the abstract decorator class, and it seems to still work. Is this abstract class present in all descriptions of this pattern simply because it provides a standard interface for all of the new decorated classes?

+1  A: 

It enables the decoration of the base class independently with various decorators in different combinations without having to derive a class for each possible combination. For example, say you want your Beverage with milk and nutmeg. Using decorators based on the abstract decorator class, you merely wrap with with Milk and Nutmeg decorators. If it was derived from Beverage, you'd have to have a MilkWithNutmegBeverage class and a MilkBeverage class and a NutmegBeverage class. You can imagine how this explodes as the number of possible combinations increases. Using the abstract decorator implementation reduces this to just one decorator class implementation per decoration.

tvanfosson
I'm not sure I understand. Yes, I am deriving 'Milk' from 'Beverage'; but 'Milk' is also being passed an instance of the 'Beverage' class which I would think is allowing me to wrap the classes as would be done with an abstract decorator class.
es11
what I am trying to say is that with the abstract decorator class, all the new decorated classes inherit from it..so why can't we just remove the middle man (and have them inherit directly from 'Beverage' PLUS passing them an instance of beverage as was done before)?
es11
I suppose you could do that, but as a child class it need not provide any additional behavior. Conceptually, the decorator, even though it implements the same interface, is **not** actually an instance of the decorated class, but rather a helper class that augments the decorated class. Basing it off a different abstract class exposes this design aspect and makes it clearer how new decorations are to be added. Implementing the decorations as child classes blurs this distinction and leaves the implementation open to child classes that may break the decoration pattern unwittingly.
tvanfosson
+1  A: 

actually i also sometimes leave out this 'middle-man' abstraction (if you don't have many decorator combinations). it decouples more but also adds complexity. in my view the main idea behind decorating is wrapping interfaces inside their own implementations.

manuel aldana
+2  A: 

A bit late to your question. I also spent quite a while to try to figure out an answer. In my case the non-concrete Decorator extends the class to be decorated ("decoree"), instead of an interface common to both the decoree and the Decorator.

After reading from different sources, it seems to me that, besides what tvanfosson said, the reason to have the concrete decorators extend an abstract, or more general, decorator is so that we don't repeat the "delegation" code over and over again.

In your case, your abstract decorator would extend the decoree and would implement the same interface as the decoree, delegating/forwarding all method calls to it. Then, the concrete decorators that you may build, would only need to implement those methods where you would want to do something different than just forward the method call to the decoree.

I hope I was clear.. :-S

Personally, I'm a bit disappointed at the need to repeat the decoree's interface in the decorator. This adds some coupling, since any time the decoree's interface changes (like getting more methods), the decorator needs to catch up.

In PHP 5.3.2 (yes, I know your question is related to Java), though, it should be possible to dynamically catch all method calls and forward them all, without the Decorator needing to know which methods are being called (in a not a very efficient way, though, having to use the Reflection API). I guess this is possible in Ruby and other languages already.

PS: This is my first answer ever in SO! ^_^

Rafa
A: 

I was wondering the same thing. Going back to the source, GOF Design Patterns, I see this under 'Implementation' in the Decorator chapter:

"Omitting the abstract Decorator class. There's no need to define an abstract Decorator class when you only need to add one responsibility. That's often the case when you're dealing with an existing class hierarchy rather than designing a new one. In that case, you can merge Decorator's responsilibility for forwarding requests to the component into the Concrete Decorator."

So at least in that case, it seems that GOF agree with you :-)

I'm not sure what the meaning of 'one responsibility' is. I'm not sure if more than 'one responsibility' would mean one concrete decorator that has more than one responsibility or more than one concrete decorator, each with its one responsibility. Either way, I don't see why the abstract Decorator is necessary. My guess is that tvanfosson's answer (in his comment on his own answer) is the right one - that once you start creating a number of decorating classes, it clarifies the design decision to group them under a superclass. On the other hand, where there is just one class, it perhaps makes the design decision less clear if you add in a second class that just sits as a pointless middle-man between base component and decorator (having said that, it's fairly likely that you'll want to add more at some point, so maybe better to include the abstract decorator even in the single case...)

At any rate, seems like it's to do with making the design clear, rather than the being the difference between the code working and not.

Jeremy
A: 

In the case of the Decorator pattern, inheritance is being used for type matching. This is not the typical reason for sub-classing. The normal reason for sub-classing is to inherit behavior

To make this distinction clear, it makes sense to sub-class Beverage with CondimentDecorator because the CondimentDecorator class makes the distinction between a drink implementation (like DarkRoast) and condiment (like Mocha) clear. Consider for example you were tasked to come up with a menu for StarBuzz just by looking at the code. You would immediately know which are "base" beverages and which condiments by looking as the base class. DarkRoast's base class is Beverage. Mocha's base class is CondimentDecorator.

Still, I think it might make more sense in Java to implement the Beverage abstract class as an interface instead. According to the book, the code didn't use this approach because StarBuzz already had an abstract Beverage class (p 93) and an abstract base component is the historical approach to implementing the pattern.

hgilson