PTOM: The Decorator Pattern

For the month of November, Pablo’s Topic of the Month is Design Patterns. I will be talking about the Decorator design pattern in this post.

The Decorator Pattern was originally coined by The Gang Of Four (GoF). It is a commonly used pattern for extending functionality dynamically at runtime. This is in contrast to a common OOP technique that everyone knows called inheritance. At it’s most basic level, think of the Decorator pattern as a wrapper with the intent to modify/attach additional behavior to an underlying class.

This is one of the easiest patterns to grasp and understand, as well as to put to use. We will use an example of a coffee shop, let’s start with a class that is used to represent a cup of coffee available in the shop. Here we have the ICoffee and Coffe interface and class:

public interface ICoffee
{
    string Name { get; }
    decimal Total { get; }
}
 
public class Coffee : ICoffee
{
    public string Name
    {
        get { return "Coffee"; }
    }
 
    public decimal Total
    {
        get { return 0.75m; }
    }
}

We have an interface that defines behavior for a cup of Coffee, and then we have a concrete class that represents a Coffee. Something to take note of here is the fact that the GoF sample uses an abstract base class for Coffee instead of my ICoffee interface. The abstract base class is then also used when implementing the decorator pattern. In other samples, people use interfaces instead of ABC’s, I usually opt for interfaces to start and then refactor to ABC if it is warranted. Use your judgement here. This is a pretty basic example so an ABC isn’t really needed.

Now let’s say we want to add the ability to have a customer add an extra shot of espresso to their latte. Normally you would do this with traditional inheritance like so:

public class CoffeePlusEspresso : Coffee
{
    public new decimal Total
    {
        get { return base.Total + .5m; }
    }
    public new string Name
    {
        get { return string.Format("{0} w/ Extra shot of espresso", base.Name); }
    }
}

This would work, however it’s not very desirable. Eventually as you add more and more permutations, (Coffee w/ Espresso, Coffee w/ Espress and Whip cream, etc..) it would lead to a class explosion and you would have a new class for every new combination of ingredients someone could have for a cup of coffee. A better option would be if we could add or “decorate” the original cost and name with our added options. Enter the Decorator Pattern.

The first step in implementing the decorator pattern is to define an abstract base class that all of your decorators can derive from. This helps enforce the DRY principle by having the code that implements the ICoffee interface. Commonly, this ABC will only be calling the passed in or “decorated” object. This way, you only need to extend the properties/methods you want in the decorators and eliminates the need to return the decorated properties/methods in each decorator.

Here is our base class that I have called IngredientDecorator:

public abstract class IngredientDecorator : ICoffee
{
    protected ICoffee _decoratedCoffee;
 
    protected IngredientDecorator(ICoffee decoratedCoffee)
    {
        _decoratedCoffee = decoratedCoffee;
    }
 
    public virtual string Name
    {
        get { return _decoratedCoffee.Name; }
    }
 
    public virtual decimal Total
    {
        get { return _decoratedCoffee.Total; }
    }
}

As you can see here, our base decorator implements the ICoffee interface by just calling the underlying ICoffee properties that we passed in the constructor. Very simple and to the point. Now we can start to create our concrete decorators that will extend the behavior of our Coffee class. Lets start with our original Espresso example and create an EspressoShotDecorator class.

public class EspressoShotDecorator : IngredientDecorator
{
    public EspressoShotDecorator(ICoffee decoratedCoffee) : base(decoratedCoffee)
    {
    }
 
    public override string Name
    {
        get { return string.Format("{0}, shot of espresso", base.Name); }
    }
 
    public override decimal Total
    {
        get { return base.Total + 0.50m; }
    }
}

We can now create a Coffee instance, pass it to an EspressoShotDecorator and print out the grand total and modified name by calling EspressoShotDecorator.Name/EspressoShotDecorator.Total as shown here:

Coffee plainCoffee = new Coffee();
EspressoShotDecorator espressoShotDecorator = new EspressoShotDecorator(plainCoffee);
 
Console.WriteLine("Name of your coffee: {0}", espressoShotDecorator.Name);
Console.WriteLine("Cost: {0}", espressoShotDecorator.Total);
 
// Name of your coffee: Coffee, shot of espresso
// Cost: 1.25

This is where it starts to become really flexible. Let’s say we also have a “Whip Cream” topping that we want to add as an ingredient. To add this functionality to our application, all we need to do is create a class that represents that single item and we can then begin to chain together the options when someone is asking for their cup of coffee with additional options. The options they have are now interchangable and dynamic. Here is the WhipCreamDecorator:

public class WhipCreamDecorator : IngredientDecorator
{
    public WhipCreamDecorator(ICoffee decoratedCoffee) : base(decoratedCoffee)
    {
    }
 
    public override string Name
    {
        get { return string.Format("{0}, whip cream", base.Name); }
    }
 
    public override decimal Total
    {
        get { return base.Total + 0.25m; }
    }
}

Adding this to the mix and then chaining it on top of the EspressoShotDecorator would yield the following results:

WhipCreamDecorator whipCreamDecorator = new WhipCreamDecorator(espressoShotDecorator);
 
Console.WriteLine("Name of your coffee: {0}", whipCreamDecorator.Name);
Console.WriteLine("Cost: {0}", whipCreamDecorator.Total);
 
// Name of your coffee: Coffee, shot of espresso, whip cream
// Cost: 1.50

You can now see how this can be flexible in dynamically modifying and extending behavior at runtime. If you want to be really cool, you can hook up the classes to an IoC framework and chain together these objects through a configuration. This is even more flexible than the above approach because you could modify behavior by changing your configuration for the IoC framework. An excellent example of this was already posted by Alex Henderson (a.k.a The Bitter Coder) in his series on Castle Windsor tutorials

As you can see the Decorator Pattern is a powerful, easy to use/implement, flexible design pattern that should be in everyones arsenal. Please post comments any derivations that you have found useful of the Decorator Pattern. Till next time!

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Sean Chambers

I am a Senior software developer from Palm Coast, Florida. An advocate of Domain Driven Design, Behavior Driven Development, creator of FluentMigrator and community activist. I am married to my beautiful wife Erin and am the proud father of two wonderful children. I currently reside at ACI, a local insurance industry/mortgage software company that excels in creating solutions using Agile methodologies.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Dave the Ninja

    I always think the decorator pattern is very similar to the Adapter pattern.

    Both very very useful patterns.

    Great article!

    Dave the Ninja

  • http://www.lostechies.com/members/schambers/default.aspx schambers

    @Dave
    The decorator is similar in behavior to the adapter pattern. The main difference being the intent of the adapter is to change one interface into another in order to be able to work with a system that you couldn’t normally work with.

    While the structure is similar, the intent is different.

    Thanks for the kind words!

  • http://blogger.forgottenskies.com Steve

    Excellent post – thank you for explaining the decorator pattern.

    Question: is there concern of an ‘explosion of decorator classes’ ?

  • http://www.lostechies.com/members/schambers/default.aspx schambers

    @Steve

    I suppose you could say that is a concern, but an acceptable concern. You would need to contain the additional logic somewhere. One class per behavior would be acceptable in my eyes.

  • Brad Mead

    Good example… Thanks for a novel context (Coffee) in which to couch the understanding.

  • Mike

    Great post! very clear example, I posted about an example of employing decorator to add extra behaviour a while back http://journalofasoftwaredev.wordpress.com/2008/03/21/multi-search-engine-enhancement-using-design-patterns/ be interesting to see what you think :)

  • Pat

    Suppose your object model was a little more deep than just ICoffee:

    ICoffee <- ILatte <- IX <- IY <- IZ

    Whip cream, chocolate, etc. could only be added to IZ and not ICoffee directly. The decorator provides dynamic extensibility which is nice, but now something that decorates IZ has to also wrap all members of ICoffee, ILatte, IX, and IY.

    If any aspect of that hierarchy changes, your decorator has to be updated. Does this present a maintenance issue? Are their ways to work around this?

  • http://www.lostechies.com/members/schambers/default.aspx schambers

    @Pat

    I suppose if your graph is that deep, then the easiest way to accomplish that is still with ABC’s for the base decorator.

    This is a good question though. While I have not had decorators that were that complex heirarchy wise, I would be interested if anyone else has come across a situation like that.

  • Ed

    @ Brad Mead

    Not really, the Head First Design Patterns book used the coffee example to illustrate the Decorator pattern.

    @ schambers

    You could have saved yourself the effort of writing this (otherwise good) post and just linked straight to the freely available chapter 3 of DHDP:

    http://oreilly.com/catalog/hfdesignpat/chapter/ch03.pdf

  • gunasekaran sambandhan

    @ guna

    Great Article!
    Very clean explaination of Decorator pattern. That forcing me to ask one question..
    Q: It seems here this concept is violating one of the SOLID priniciple (
    FUNCTIONS THAT USE … REFERENCES TO BASE CLASSES MUST BE ABLE TO USE OBJECTS OF DERIVED CLASSES  WITHOUT KNOWING IT. – Liskov Substitution Principle)

    please correct me if i am wrong..