This is part of a series of posts demonstrating software design patterns using C# and .NET. The patterns are taken from the book Design Patterns by the Gang of Four. Here's the series index page.

What Is This Pattern?

The Decorator design pattern seeks to add new functionality to an existing object without changing that object's definition.

In other words, it wants to add new responsibilities to an individual instance of an object, without adding those responsibilities to the class of objects. Decorator can be thought of as an alternative to inheritance.

The Rundown

  • Type: Structural
  • Useful? 3/5 (Sometimes)
  • Good For: Injecting new functionality into instances of objects at runtime rather than including that functionality in the class of objects.
  • Example Code: On GitHub

The Participants

  • The Component defines the interface for objects which will have responsibilities or abilities added to them dynamically.
  • The ConcreteComponent objects are objects to which said responsibilities are added.
  • The Decorator maintains a reference to a Component and defines and interface that conforms to the Component interface.
  • The ConcreteDecorator objects are the classes which actually add responsibilities to the ConcreteComponent classes.

A Delicious Example

To demonstrate how we might use the Decorator design pattern, let's imagine that we run a farm-to-table restaurant.

A set of tables at an outdoor restaurant, ready for the lunch rush.

The idea of our restaurant is that we only make dishes from ingredients that are available from our farm; that is, we can only make things from the crops that we grow. Further, sometimes we get a rush on particular dishes, and when this happens we occasionally need to stop selling particular dishes until we can harvest more ingredients (after all, veggies don't grow overnight). In this case, then, we need to be able to mark certain dishes as "sold out" once we run out of ingredients.

To model this, let's first define our Component participant, which is our abstract RestaurantDish class:

/// <summary>
/// The abstract Component class
/// </summary>
abstract class RestaurantDish  
{
    public abstract void Display();
}

We also need a couple ConcreteComponent participant classes representing the individual dishes we serve. These classes only implement their properties, not the number of dishes available (which is the responsibility of the Decorator).

/// <summary>
/// A ConcreteComponent class
/// </summary>
class FreshSalad : RestaurantDish  
{
    private string _greens;
    private string _cheese; //I am going to use this pun everywhere I can
    private string _dressing;

    public FreshSalad(string greens, string cheese, string dressing)
    {
        _greens = greens;
        _cheese = cheese;
        _dressing = dressing;
    }

    public override void Display()
    {
        Console.WriteLine("\nFresh Salad:");
        Console.WriteLine(" Greens: {0}", _greens);
        Console.WriteLine(" Cheese: {0}", _cheese);
        Console.WriteLine(" Dressing: {0}", _dressing);
    }
}

/// <summary>
/// A ConcreteComponent class
/// </summary>
class Pasta : RestaurantDish  
{
    private string _pastaType;
    private string _sauce;

    public Pasta(string pastaType, string sauce)
    {
        _pastaType = pastaType;
        _sauce = sauce;
    }

    public override void Display()
    {
        Console.WriteLine("\nClassic Pasta:");
        Console.WriteLine(" Pasta: {0}", _pastaType);
        Console.WriteLine(" Sauce: {0}", _sauce);
    }
}

We need to decorate those dishes at runtime with the ability to keep track of whether or not we've exhausted all the ingredients. To do this, let's first implement a Decorator abstract class (which, in a rare case of name matching purpose, is also our Decorator participant):

/// <summary>
/// The abstract Decorator class.  
/// </summary>
abstract class Decorator : RestaurantDish  
{
    protected RestaurantDish _dish;

    public Decorator(RestaurantDish dish)
    {
        _dish = dish;
    }

    public override void Display()
    {
        _dish.Display();
    }
}

Finally, we need a ConcreteDecorator for keeping track of how many of the dishes have been ordered.

/// <summary>
/// A ConcreteDecorator. This class will impart "responsibilities" onto the dishes 
/// (e.g. whether or not those dishes have enough ingredients left to order them)
/// </summary>
class Available : Decorator  
{
    public int NumAvailable { get; set; } //How many can we make?
    protected List<string> customers = new List<string>();
    public Available(RestaurantDish dish, int numAvailable) : base(dish)
    {
            NumAvailable = numAvailable;
    }

    public void OrderItem(string name)
    {
        if (NumAvailable > 0)
        {
            customers.Add(name);
            NumAvailable--;
        }
        else
        {
            Console.WriteLine("\nNot enough ingredients for " + name + "'s order!");
        }
    }

    public override void Display()
    {
        base.Display();

        foreach(var customer in customers)
        {
            Console.WriteLine("Ordered by " + customer);
        }
    }
}

Like many of the other patterns, all of this setup comes to fruition in the Main(). First, we define a set of dishes, then we decorate those dishes so that when we run out of ingredients we can notify the patron. Finally, we order those dishes. The complete main method looks like this:

static void Main(string[] args)  
{
    //Step 1: Define some dishes, and how many of each we can make
    FreshSalad caesarSalad = new FreshSalad("Crisp romaine lettuce", "Freshly-grated Parmesan cheese", "House-made Caesar dressing");
    caesarSalad.Display();

    Pasta fettuccineAlfredo = new Pasta("Fresh-made daily pasta", "Creamly garlic alfredo sauce");
    fettuccineAlfredo.Display();

    Console.WriteLine("\nMaking these dishes available.");

    //Step 2: Decorate the dishes; now if we attempt to order them once we're out of ingredients, we can notify the customer
    Available caesarAvailable = new Available(caesarSalad, 3);
    Available alfredoAvailable = new Available(fettuccineAlfredo, 4);

    //Step 3: Order a bunch of dishes
    caesarAvailable.OrderItem("John");
    caesarAvailable.OrderItem("Sally");
    caesarAvailable.OrderItem("Manush");

    alfredoAvailable.OrderItem("Sally");
    alfredoAvailable.OrderItem("Francis");
    alfredoAvailable.OrderItem("Venkat");
    alfredoAvailable.OrderItem("Diana");
    alfredoAvailable.OrderItem("Dennis"); //There won't be enough for this order.

    caesarAvailable.Display();
    alfredoAvailable.Display();

    Console.ReadKey();
}

When we run the app, the output looks like this:

A screenshot of the sample app in action, showing two dishes ordered, one of which was ordered too many times.

As you can see, Dennis can't order the fettuccine alfredo because we've run out of ingredients.

Will I Ever Use This Pattern?

Maybe? I haven't personally used it outside of demos, but I can see it being useful in many circumstances. I'm also wondering if maybe ASP.NET MVC's attributes count as usage of the Decorator pattern, but I'm not sure (so if anyone can clear this up for me, I'd be much obliged).

Summary

The Decorator pattern seeks to dynamically add functionality to instances of objects at runtime, without needing to change the definition of the instance's class. This is especially useful in scenarios where different instances of the same object might behave differently (such as dishes in a restaurant or items in a library).

As always, I like to provide code with my tutorials, so the repository for this pattern is over on GitHub and contains all of the sample code used here.

Man, all this food is making me hungry. Where'd that caesar salad I had go?

A caesar salad with dressing

Ah, found it! 'Scuse me whilst I eat my lunch.

Happy Coding!

Get My eBook FREE!

Did you enjoy this post? This article and 21 others are also in my free eBook, "The Daily Design Pattern", which you can get just by signing up for my email list.