.NET Tutorials, Forums, Interview Questions And Answers
Welcome :Guest
 
Sign In
Register
 
Win Surprise Gifts!!!
Congratulations!!!


Top 5 Contributors of the Month
david stephan

Home >> Articles >> Architecture/Pattern >> Post New Resource Bookmark and Share   

 Subscribe to Articles

Dynamically extending responsibilities using Decorator Pattern

Posted By:Jean Paul       Posted Date: December 09, 2010    Points: 75    Category: Architecture/Pattern    URL: http://www.dotnetspark.com  

I am here with an example oriented design pattern. The design pattern is Decorator.
 

According to Gof: "Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality"

Closed for Modification and Open for Extension


One of the main challenges we face in development is Change.  The Closed for Modification and Open for Extension principle says a new functionality can be added by keeping the original code unchanged.

Example:

You have an Album class today which is just blank now.  Tomorrow if the customer wants a Christmas tree on that.. What would be our approach?
We will modify the original Album class to incorporate the Christmas tree on it.  This should not be the best approach.  There is a better approach to this.  We can still keep the Album class unchanged and add the Christmas tree to it.  Everything happens in the runtime. that is the cool part of it.

Some more examples


We can see real life controls like Form, Button etc.  There would be a Form class which having inbuilt functionality.  Still the user can use it and add new controls on it / extend the functionality.  Here we will be basically deriving from the existing Form/Button class and add new methods or properties to it.
The difference between the above approach and Decorator pattern is that, in the Decorator pattern, we are assigning the responsibility in the runtime.

Conclusion on Change


So basically we can conclude that whenever changes are required, the possible solutions could be:
·  Change the original class
·  Subclass it and create instance of subclass
·  Use Decorator Pattern and still using the original class instance
Here we are going to see how we can use Decorator Pattern to help with the following scenario.

Requirement


The requirement here would be to provide a default Album object and based on dynamic requirement from the user in runtime, we have to draw other pictures to the album.



Design

Our first class would be the Album class which has a Graphics object as parameter.

It contains a Draw() method which is virtual and just clears the graphics object.

public class Album
{
  public Graphics Graphics
  {
  get;
  set;
  }
 
  public Album()
  {
  }
 
  public Album(Graphics graphics)
  {
  Graphics = graphics;
  }
 
  public virtual void Draw()
  {
  Graphics.Clear(Color.White);
  }
}

Decorator

We are adding the class named AlbumDecorator which will serve as the base class for all decorators.

public abstract class AlbumDecorator : Album
{
  protected Album _album;
 
  public AlbumDecorator(Album album)
  {
  _album = album;
  }
 
  public override void Draw()
  {
  _album.Draw();
  } 
}


It takes an Album class as parameter in the constructor. 

There are ChristmasTreeDecorator, SantaClausDecorator, StarDecorator deriving from AlbumDecorator:

public class ChristmasTreeDecorator : AlbumDecorator
public class SantaClausDecorator : AlbumDecorator
public class StarDecorator : AlbumDecorator


Each class deriving from AlbumDecorator would be having it's own picture to draw.

Invoking


In the main form we create an instance of Album class and assigns it to form field _album.

private Album _album;
_album = new Album(_graphics);
_album.Draw();


In the runtime, when user wantedChristmas Tree, instance of ChristmasTreeDecorator is created.

_album = new ChristmasTreeDecorator(_album);
_album.Draw();


In the above code we can see the same _album.Draw() method is called.

How it works


Whenever we call the Draw() method of a decorator class, it in turns calls the original Album.Draw().  After that it will call it's own Draw() method.  In this way we can pass the same album instance to multiple decorators.  If there are 10 decorators, all the decorator Draw() methods will be invoked.
You can test this placing a breakpoint inside the StarDecorator Draw() method.

Note


Using decorator we can add dynamic responsibilities to an object in runtime.  This provides us the flexibility of creating instance of decorators on need base.  This would provide real advantage in scenarios like the additional responsibility instance consists of much memory usage.

 Subscribe to Articles

     

Further Readings:

Responses

No response found. Be the first to respond this post

Post Comment

You must Sign In To post reply
Find More Articles on C#, ASP.Net, Vb.Net, SQL Server and more Here

Hall of Fame    Twitter   Terms of Service    Privacy Policy    Contact Us    Archives   Tell A Friend