Click here to Skip to main content
Click here to Skip to main content

Decorator Design Pattern

By , 4 May 2011
 

You can see this and other great articles on design patterns here.

The decorator design pattern allows you to add features to an object dynamically. An example would be the search functionality in an application. You may need to search for employees such as salary, zip code, skills, and so on. The user may choose to enter any combination of search criteria, and it would be a daunting task trying to figure out all the possible combinations as the number of fields grow. The decorator pattern allows you to dynamically add only the fields that the user is searching for.

In the decorator pattern, each feature is represented by a class. Therefore, if you have 10 features, then you will have 10 decorator classes.

Let’s look at the UML of the decorator pattern first, then we will look at an example to see how it works. Below is the UML of the decorator design pattern:

  • The IComponent interface defines the operation, or the features that the decorators can perform.
  • The StartComponent class is the starting object that you can dynamically add features to. You will create this object first and add features to it.
  • The Decorator class is an abstract class and is the parent class of all the decorators. While it implements the IComponent interface to define the operations, it also contains a private variable input that points to the object to be decorated. The input variable is simply assigned in the constructor.

The constructor for the Decorator class is simply:

public Decorator(IComponent i)
{ 
    input = i;
}
  • The ConcreteDecorator classes are the actual decorator classes that can add features. You can have as many ConcreteDecorator classes as you like, and each will represent a feature that can be added.

Let's do an example and see how it works. In our example, you have a plain ice cream where you can add different combinations of toppings to it. The UML will be:

  • The IComponent interface has the AddTopping method that all the classes implement.
  • The PlainIceCream class is the starting point object.
  • The Topping abstract class is the parent class of all the decorators. In its constructor, it assigns the parameter of type IComponent to the input variable, which points to the object to be decorated.
  • The PeanutTopping and the CandyTopping are the decorators, where each decorator has its own implementation on how to add the toppings.

The client code to use the decorators will be:

IComponent a = new PlainIceCream();    //your starting point

IComponent b = new PeanutTopping(a);  //notice you pass in the IComponent 
				   //that you want to decorate

IComponent c = new CandyTopping(b);    //add another decorator since the 
				    //user also likes candy

c.AddTopping(); 	//do all the operations of AddTopping() of 
		//PlainIceCream, PeanutTopping, and CandyTopping in one call

The code above allows you to add features dynamically using any combinations the user may choose.

The AddTopping method of the decorators will call previous decorators first, followed by the decoration that you define:

public void AddTopping()
{
    input.AddTopping();   //make the previous object do the decorations first
    //then add the implementation here to add the new feature
}

Below are the implementation code and the output of the decorator design pattern from our example. Notice that you can add any combinations of features dynamically in the client code:

class Program
{
    static void Main(string[] args)
    {
        IComponent a = new PlainIceCream();
        IComponent b = new CandyTopping(a);
        IComponent c = new PeanutTopping(b);
        IComponent d = new NutsTopping(c);
        d.AddTopping();
    }
}

public interface IComponent
{
    void AddTopping();
}

public class PlainIceCream : IComponent
{
    void IComponent.AddTopping()
    {
        Console.WriteLine("Plain Ice Cream ready for some toppings");
    }
}

public abstract class Topping : IComponent
{
    protected IComponent input;

    public Topping(IComponent i)
    {
        input = i;  //store the item to be decorated
    }

    void IComponent.AddTopping()
    {
    }
}

public class CandyTopping : Topping, IComponent
{
    public CandyTopping(IComponent i)
        : base(i)
    {
    }

    void IComponent.AddTopping()
    {
        input.AddTopping();  //decorate others first
        Console.WriteLine("Candy Topping added");
    }
}

public class PeanutTopping : Topping, IComponent
{
    public PeanutTopping(IComponent i)
        : base(i)
    {
    }

    void IComponent.AddTopping()
    {
        input.AddTopping();  //decorate others first
        Console.WriteLine("Peanut Topping added");
    }
}

public class NutsTopping : Topping, IComponent
{
    public NutsTopping(IComponent i)
        : base(i)
    {
    }

    void IComponent.AddTopping()
    {
        input.AddTopping();  //decorate others first
        Console.WriteLine("Nuts Topping added");
    }
}

Liked this article? You can see this and other great articles on design patterns here.

License

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

About the Author

DevLake
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy apologiesmvpPete O'Hanlon5 May '11 - 3:38 
Your blog post was not the place for a very public spat with one of the other members. I apologize that you got dragged into it. If it's any consolation, I am enjoying your blog posts. They are clear, concise and well written. Keep up the good work.

Forgive your enemies - it messes with their heads

My blog | My articles | MoXAML PowerToys | Mole 2010 - debugging made easier - my favourite utility


GeneralMy vote of 5mentorKeith Barrow5 May '11 - 2:26 
Counteracting Blakecool's vote: He is a sockpuppet for Bill Sergio. Looks like a good article any way.
GeneralMy vote of 1memberblakecool5 May '11 - 1:35 
I have watched this immature back and forth and had to comment. These postings have bad code in them period. Second the person who complained about spamming--and it is spamming is then criticized? Why? All these clowns need to grow up!
GeneralRe: My vote of 1memberCDP18025 May '11 - 2:07 
Which part of 'get lost' did you not quite understand?
"I just exchanged opinions with my boss. I went in with mine and came out with his." - me, 2011
---
I am endeavoring, Madam, to construct a mnemonic memory circuit using stone knives and bearskins - Mr. Spock 1935 and me 2011


GeneralMy vote of 1memberBill SerGio, Infomercial King4 May '11 - 22:21 
too short and the sample code isn't practical and would fail in a real application. This kind of post is misleading to beginners who think this code is good code.
GeneralMy vote of 5memberCS20114 May '11 - 22:14 
Sweet and simple.Well explained for a beginner.Good Job
GeneralPeople who have NOT published an article should NOT be allowed to vote [modified]memberBill SerGio, Infomercial King4 May '11 - 20:06 
I would eliminate this voting system on articles because the rating does not reflect the quality of the article or code. In fact, I can show hundreds of articles posted here that have ratings under 3 that deserve a 5. While the editors have tried to help this inequity by making people who give a low rating explain their reason this has NOT worked at all.
 
An author should be able to select an option to NOT have their article rated if you are going to completely remove the rating system but at the very least do NOT allow anyone to post a rating unless they have written an article or say at least 3 articles themselves and that would help to eliminate bogus ratings.
 
It has to be very upsetting to any author that takes the time to write an article when some clown posts a 1 rating.
 
Change the system. I am so annoyed at this rating crap that I don't think I will ever bother to post an article on this site again and I will post on other sites that have no rating system that allows morons to post crap. Mad | :mad:
http://www.GeminiGroupTV.com
modified on Thursday, May 5, 2011 2:24 AM

GeneralRe: People who have NOT published an article should NOT be allowed to vote [modified]memberAddy Tas2 Apr '12 - 2:02 
With the risk of being shot; you voted a big fat 1 but the motivation seems to be targeted against CodeProject itself. I do not consider this fair to the author of this article.
Does this comment, which definetly has truth in it, not belong in another part of the site? e.g. the Lounge?
 
Cheers, AT
Cogito ergo sum

GeneralMy vote of 5memberEdMan1964 May '11 - 9:50 
Same as Pete, undoing what the moron has done Poke tongue | ;-P
GeneralRe: My vote of 5 [modified]memberEdMan1964 May '11 - 10:45 
I believe if I were to meet you face to face I would give you a good British gentlemen's owning Poke tongue | ;-P I call you names in a vague attempt to drop to your level and make you realise your mistake. Perhaps an admittance that you were wrong is in order, no?

modified on Wednesday, May 4, 2011 4:55 PM

GeneralRe: My vote of 5memberEdMan1964 May '11 - 11:26 
Bill SerGio, Infomercial King wrote:
in a bar

Apperently America is different but in England, at the very least you would be arrested, but perhaps that is best... :|
GeneralRe: My vote of 5mvpAspDotNetDev4 May '11 - 11:31 
Bill SerGio, Infomercial King wrote:
I would never admit being wrong

 
Ah, so that's your way of admitting you are wrong? Apology accepted. Smile | :)
 
Bill SerGio, Infomercial King wrote:
just out all the pent up frustration one has in general

 
I know this guy who sells pills that can help with that. Wink | ;)

GeneralMy vote of 5mvpPete O'Hanlon4 May '11 - 9:47 
It's a good explanation.
 
[note]This comment was moderated to remove the harsh comments.
GeneralRe: My vote of 5memberBill SerGio, Infomercial King4 May '11 - 10:16 
You seem to like to call people names? You call me a "moron" but you seem to be insensitive to teh fact that it is insulting to mentally challenged people but you use it anyway. Do you also use the "N" word? I am sure you do when you are drinking in those Irish bars you hang out in Peter.
 
But I ahve businesses to run even though it has been fun reading your childish remarks and insults about mentally challenged people.
http://www.GeminiGroupTV.com

GeneralRe: My vote of 5memberCDP18024 May '11 - 20:13 
A rose, by any other name...
 
If the shoe fits, just put it on Smile | :)
"I just exchanged opinions with my boss. I went in with mine and came out with his." - me, 2011
---
I am endeavoring, Madam, to construct a mnemonic memory circuit using stone knives and bearskins - Mr. Spock 1935 and me 2011


GeneralYou have never posted an articlememberBill SerGio, Infomercial King4 May '11 - 20:23 
You have never posted an article so your opinion is worthless and I guess teh reason we see NO articles from you is your lack of talemt and maybe you can't read or write too well? Post an article and then you will have the right to comment you loser.
http://www.GeminiGroupTV.com

GeneralRe: You have never posted an articlememberCDP18024 May '11 - 20:28 
You would not care to come and tell me that in the face, right? Then I will have enough material for an article on how to wipe the floor with a moron Smile | :)
"I just exchanged opinions with my boss. I went in with mine and came out with his." - me, 2011
---
I am endeavoring, Madam, to construct a mnemonic memory circuit using stone knives and bearskins - Mr. Spock 1935 and me 2011


GeneralRe: You have never posted an articlememberBill SerGio, Infomercial King4 May '11 - 21:44 
Listen I live in Miami FL and you are invited to visit me. I am easy to find and I would love to express my feeling in person regarding your retarded mother who I understand is still working the streets?
http://www.GeminiGroupTV.com

GeneralRe: You have never posted an articlememberCDP18024 May '11 - 21:52 
I'm sure the state of Florida denies all knowledge of your existence, but a surviving Neanderthal should be of real interest to all biologists Smile | :)
"I just exchanged opinions with my boss. I went in with mine and came out with his." - me, 2011
---
I am endeavoring, Madam, to construct a mnemonic memory circuit using stone knives and bearskins - Mr. Spock 1935 and me 2011


GeneralRe: You have never posted an articlememberBill SerGio, Infomercial King4 May '11 - 21:58 
I live in Old Cutler Bay in Miami and it is real easy to find me--come on coward let's see you tell me that crap to my face!
http://www.GeminiGroupTV.com

GeneralRe: You have never posted an articlememberCDP18024 May '11 - 22:06 
I believe, that's what I wrote a few posts ago. Is insulting my poor old mom and aping my posts all you can come up with? Ok, it must be hard to walk, think and keeping your knuckles from dragging over the floor all at once. Insult me all you want, mental flyweight, but at least try not to bore me.
"I just exchanged opinions with my boss. I went in with mine and came out with his." - me, 2011
---
I am endeavoring, Madam, to construct a mnemonic memory circuit using stone knives and bearskins - Mr. Spock 1935 and me 2011


GeneralRe: You have never posted an articlememberBill SerGio, Infomercial King4 May '11 - 22:13 
Goodnight punk.
http://www.GeminiGroupTV.com

GeneralHope you are finished all this useless materialmemberBill SerGio, Infomercial King4 May '11 - 9:18 
I just wanted to know if you just copied all these worthless examples from a book? And why did you post it all at one time? Have you been saving this to try and impress us with your talent? I don't see any novel code or practical application and the stuff you posted is illustrated in many places.
http://www.GeminiGroupTV.com

GeneralRe: Hope you are finished all this useless material [modified]mvpPete O'Hanlon4 May '11 - 9:41 
Message removed because my comments were too harsh, and not in keeping with the attitudes I'd like promoting on the site. To Bill, I unreservedly apologise for the harsh tone of my comments, but I still maintain that downvoting the blog entry because it did not meet up to the standards of a full article is unwarranted.

Forgive your enemies - it messes with their heads

My blog | My articles | MoXAML PowerToys | Mole 2010 - debugging made easier - my favourite utility


modified on Thursday, May 5, 2011 8:48 AM

GeneralRe: Hope you are finished all this useless materialmemberDaveAuld4 May '11 - 9:48 
Pete, are you not going against your own words of messages in the past......dnftt Roll eyes | :rolleyes:
Dave
Find Me On: Web|Facebook|Twitter|LinkedIn

Folding Stats: Team CodeProject

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 4 May 2011
Article Copyright 2011 by DevLake
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid