Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Understanding the Decorator Pattern

4.90/5 (45 votes)
7 Feb 2013CPOL11 min read 94.3K   516  
Implementation of the Decorator pattern in C# .NET.

Background

Before zeroing in on the theories and definitions, let's take a look at a real world problem. XYZ Organizers is a recently established event management firm that takes on responsibility of wedding events from start to end. They provide three services related to a wedding event:

  • Photography
  • Videography
  • Catering

And also requires their clients to pay a certain amount as service charge. Now they came to us, ABC Technologies, to get their billing system built. Upon analyzing their requirements we said fair enough, let's get started. So we started by creating our first class, WeddingService:

C#
public class WeddingService
{
    public decimal Cost
    {
        get
        {
            return 10000;   //Service charge for overall management
        }
    }
}

Now let's extend this class to include the photography cost:

C#
public class WeddingServiceWithPhotography : WeddingService
{
    public decimal Cost
    {
        get
        {
            return base.Cost + 15000;
            //Wedding service charge + photography service charge
        }
    }
}

Now to fulfill our requirements, we need to create two more classes, WeddingServiceWithPhotographyAndVideography and WeddingServiceWithPhotographyVideographyAndCatering, to include the costs/ service charges of videography and catering.

C#
public class WeddingServiceWithPhotographyAndVideography : WeddingServiceWithPhotography
{
    public decimal Cost
    {
        get
        {
            return base.Cost + 15000;
            //Wedding service charge + photography service charge + videography service charge
        }
    }
}
C#
public class WeddingServiceWithPhotographyVideographyAndCatering : 
       WeddingServiceWithPhotographyAndVideography
{
    public decimal Cost
    {
        get
        {
            return base.Cost + 50000;   //Wedding service charge + photography service charge + 
                                        //   videography service charge + catering service charge
        }
    }
}

It is the final class, WeddingServiceWithPhotographyVideographyAndCatering, which will calculate the cost of the overall wedding service. So far, everything works as expected, our client is happy, so are we.

Note the use of inheritance to get the cost in each step. Also note that we have kept things simple by returning hard-coded amounts. In a real implementation, the amounts would've been returned based on some business logic like the duration a photographer/ videographer has to cover an event for, or for the catering service charge, the number of guests attending the event etc.

But businesses change/ grow with time and our client, XYZ Organizers, is nothing different. They are now telling us that they wish to expand their range of services and keep them flexible. That is their clients get to choose what services they want in an event. For example, the client is asking for a wedding management service with photography and videography only. We smile and reply that it's not a problem and can be done easily (because we know we have a class, WeddingServiceWithPhotographyAndVideography, which calculates wedding service cost with photography and videography only). But our faces quickly turned pale after hearing that our client is adding two more services, Stage Decoration and Hall Decoration and their clients could ask for any one or any combination of them in an event. That means we have to create classes for every combination of the services:

  • WeddingServiceWithStageDecoration
  • WeddingServiceWithHallDecoration
  • WeddingServiceWithStageAndHallDecoration
  • WeddingServiceWithStageAndHallDecorationAndCatering
  • WeddingServiceWithStageAndHallDecorationAndCateringAndPhotography
  • ...

This is a growing pain and we realize that our solution would get bloated as new services are added.

We are now seriously thinking of how we can provide a flexible solution that adds up the cost of the individual services as the client requires with the event. One possible solution could be to create a class for every service and use switch-case/ if-else statements to add up the costs with the event as required. But apart from not being a proper OO solution, that code would definitely smell (if you know what I mean) as the if-else statements grow with new services being added in time. So how can we get to a meaningful and manageable solution? We ask ourselves.

Behold the Decorator pattern!

The Decorator pattern shows us how we can solve problems like the one we saw above. The bookish definitions are:

The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
(Head First Design Patterns, O'Reilly)

The decorator pattern can be used to extend (decorate) the functionality of a certain object at run-time, independently of other instances of the same class, provided some groundwork is done at design time. This is achieved by designing a new decorator class that wraps the original class.
(Wikipedia, http://en.wikipedia.org/wiki/Decorator_pattern)

Now let's see those definitions again, but this time in our problem context:

The Decorator Pattern attaches additional responsibilities (services) to an object (wedding event) dynamically.

The decorator pattern can be used to extend (decorate) the functionality (services) of a certain object (wedding event) at run-time, independently of other instances of the same class (other wedding events).

Starting to make sense, isn't it?

To me, the Decorator pattern is more like an elegant fusion of inheritance and composition. We'll see that in a short while.

So how does the Decorator pattern work to solve such problems?

By definition, in a solution designed in the Decorator pattern, there is a component class and then there is the decorator class. The decorator class holds a reference to an object of the component's type and itself is derived from the component class.

Say what?

Yes, and theoretically the decorator classes are chained together around the component class and use delegation to give the component class new responsibilities.

Sounds scary, right? Yeah! Enough with the gibberish, let's get down to business. First take a snapshot of the UML class diagram of the Decorator pattern:

UML class diagram of the decorator pattern

Hmm, the UML diagram does seem to align with the definition. The Decorator class is derived from Component and holds a reference to a Component object. But what's with the ConcreteComponent and the ConcreteDecorator classes? Well you see in our context, the WeddingService class would be the component object and PhotographyService, VideographyService, CateringService etc. would be the decorator classes (basically those objects, the behaviour of which are to be added dynamically at run time, are made decorators). The decorator pattern requires the decorators and components be derived from same base component (we'll see later in this article why). That's why the UML diagram shows a generalized Component class from which all other concrete components and decorators are derived.

Ok. But what about the ConcreteDecorator class? It seems like the ConcreteDecorator class is derived from an abstract Decorator class. Why?

We'll try to find the answer in a moment. So according to the pattern, let's create our component interface first..

C#
public interface IEventService
{
    decimal Cost { get; }
}

and then the abstract base component class EventService which implements IEventService:

C#
public abstract class EventService : IEventService
{
    public abstract decimal Cost { get; }
}

Next to create is the concrete component class WeddingService, which we'll derive from EventService:

C#
public class WeddingService : EventService
{
    public override decimal Cost
    {
        get
        {
            return 10000;   //Service charge for overall management
        }
    }
}

..and the abstract Decorator class, which we name EventServiceDecorator:

C#
public abstract class EventServiceDecorator : EventService
{
    public IEventService EventServiceObj;
    public override decimal Cost
    {
        get
        {
            return EventServiceObj.Cost;
        }
    }
 
    public EventServiceDecorator(IEventService eventService)
    {
        this.EventServiceObj = eventService;
    }
}

A point to be noted here is that we don't necessarily have to create an abstract component class and can directly create our concrete component and abstract decorator classes just by implementing the IEventService interface. It solely depends on our problem context.

We can see that the constructor of the EventServiceDecorator abstract class takes in an IEventService object as a parameter and stores it in an instance variable of type IEventService. This is where composition takes place. Also note that the EventServiceDecorator abstract class overrides the Cost property of its base class which is the EventService class. This overridden Cost property simply returns the Cost of whatever service the instance variable EventServiceObj represents.

Let's take a look at our concrete decorator class, i.e., the PhotographyService class:

C#
public class PhotographyService : EventServiceDecorator
{
    public PhotographyService(IEventService eventService)
        : base(eventService)
    {
 
    }
 
    public override decimal Cost
    {
        get
        {
            return base.Cost + 15000;
            //Cost of whatever event service represented by EventService + Photography service
        }
    }
}

We can see that the constructor of our concrete PhotographyService decorator class simply calls its base version passing the IEventService parameter. So what is this IEventService parameter that gets passed in to the constructors? Well, it is indeed the IEventService that PhotographyService is going to decorate. Take a look at the overridden Cost property's get accessor. It first retrieves the cost of IEventService object that was passed in to the constructor by accessing the Cost property on its base class and then adds up PhotographyService's own cost. This is how PhotographyService's behavior gets added to the passed IEventService object. In this case, it is adding up Photography cost to the cost of whatever service EventServiceObj represents, be it WeddingService, SeminarService etc. And thus we can see how new responsibility (in our case a new service, photography) gets added to an existing object (wedding service) through composition of the PhotographyService decorator with a concrete service object (wedding service) or another decorator object. Wait, another decorator object? How come? We'll see that in a moment.

I think we're now pretty much clear about the purpose of the abstract decorator class. But at the same time you possess the right to say that we could have derived the PhotographyService class directly from EventService (IEventService), put the EventService (IEventService) instance variable in the concrete PhotographyService class instead of inside the abstract decorator class and called the Cost get accessor on it directly in the overridden Cost get accessor of the PhotographyService and then could have added Photography's own cost, thus eliminating the need for an abstract decorator class in the process. Yes we could have. But then we would have to put the same IEventService instance variable in all concrete decorator classes and write the same code in all of the overridden Cost get accessors over and over again. Moreover, I wanted to move the responsibility of manipulating the IEventService object (however small it is) that's being decorated, to the abstract decorator class. In future there might arise some common logic depending on business that gets applied to the object before being decorated. And then there is that tradition of implementing the Decorator pattern with an abstract decorator class Wink | <img src=

So there remains one more question. Why do we have to derive the decorator class from the abstract component class/ component interface (IEventService), effectively making it a component? Exactly, to make it a component, to allow it to be interchanged with other components. Remember I talked about chaining the decorators together to make the decorator pattern work? We'll see now how this unfolds. But first let's create one more service decorator:

C#
public class CateringService : EventServiceDecorator
{
    public CateringService(IEventService eventService)
        : base(eventService)
    {
 
    }
 
    public override decimal Cost
    {
        get
        {
            return base.Cost + 50000;
            //Cost of whatever event service represented by EventService + Catering service
        }
    }
}

and also create one more concrete event service, SeminarService class:

C#
public class SeminarService : EventService
{
    public override decimal Cost
    {
        get
        {
            return 5000;   //Service charge for overall management
        }
    }
}

Assume there's a Seminar event to be managed and the client only wants photography and catering services. We can calculate the bill for all the services requested the following way:

C#
IEventService seminarService = new SeminarService();
PhotographyService photographyService = new PhotographyService(seminarService);
CateringService cateringService = new CateringService(photographyService);
Console.WriteLine(cateringService.Cost);

First of all, we created the original event service, that is the SeminarService concrete class, i.e., the concrete component. Then added the photography service and finally the catering service. The first two lines of above code seem quite straightforward but you might be focusing in on line #3 here. Yes, we have passed the decorator that originally takes in the SeminarService object, as a parameter to another decorator. Remember I have talked about chaining the decorators a while ago? This is where inheritance comes into play and shows exactly why we derived our abstract decorator class, EventServiceDecorator, from the abstract component class EventService (a type of IEventService), to make the EventServiceDecorator nothing but another type of EventService (IEventService). Simply put, a decorator is the same type of object it is going to decorate. That's why in the case of the decorator we are conforming to the same interface as the object it is going to decorate (wrap) using inheritance to achieve the type matching. Because this decorator could again be passed in to some other decorator to be decorated with some other behavior. Had we not kept the type same, how would have we achieved this?

So let's run our sample program above in our head..

cateringService.Cost is called first which adds up its cost to the cost of the component that it is composed with, i.e., the PhotographyService object. PhotographyService, in turn, adds up its own cost to the cost of the component that it was composed with (SeminarService) and returns the total amount to the caller which is the cateringService.Cost get accessor. This results in calculating the final amount of cost for the seminar service along with photography and catering services. In the process we have chained two decorators together around a concrete component object.

Conclusion

We are adding new behavior dynamically (at runtime) to an object (component) by actually composing a decorator with that component object or another decorator (which actually is a component). The Decorator pattern is used for providing additional functionality to a particular 'object' as opposed to a 'class' of objects. And so we are achieving new behavior through composition, not through inheritance, thus achieving flexibility in mixing different types of decorators as required at runtime. Inheritance is only there to get the correct blueprint. Had we relied only on inheritance for new behavior, we would have defined behavior statically at compile time as we have seen at the start of this article resulting in bloated solution with virtually unlimited classes. 

The Decorator pattern also nicely conforms to the Open/closed principle, that is the decorator classes are open for extension but closed for modification. On that note, following is a comment made by John Brett:

"It is also worth mentioning that this pattern lends itself very well to unit testing. Each decorator is, by necessity, decoupled from the rest of the system, making it easy to supply a mock to the constructor and exercise the interface thoroughly"

Finally, I bet you already have used .NET framework classes that incorporate the decorator pattern. I leave it on you to find out. Ok, a hint: look at the Stream classes Wink | <img src=

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)