In this article we will talk about the Decorator Pattern and how to implement it in an ASP.Net application.

Agenda

Before reading this article, please go through the following articles:

  1. Design Patterns: Introduction
  2. Learn Design Pattern - Singleton Pattern
  3. Learn Design Pattern - Factory Method Pattern
  4. Learn Design Pattern - Abstract Factory Pattern
  5. Learn Design Pattern - Builder Pattern
  6. Learn Design Pattern - Prototype Pattern
  7. Learn Design Pattern - Adapter Pattern
  8. Learn Design Pattern - Composite Pattern
  9. Learn Design Pattern - Facade pattern
  10. Learn Design Pattern - Flyweight pattern

    What is Decorator Pattern?


    When to use?

    Practical Example

    Consider we have a 2-player Gaming System.

    As the player progresses he is awarded with some weapons like Gun, Knife or both.

    Our task is to create a web page which will get the player's description by his/her type and weapon he/she has.

    The output should look like this:


    What-is-Decorator-Pattern.jpg

    Player Structure


    player-structure.jpg

    In short our task is to decorate Players with weapons at runtime.

    Solution 1

    Create 2 properties in the base called HasGun and HasKnife.

    Solution 2

    Create 6 new classes called Player1WithGun, Player1WithKnife, Player1WithGunAndKnife, Player2WithGun, Player2WithKnife and Player2WithGunAndKnife.


    It's obvious we are accomplishing nothing but creating maintenance nightmares for ourselves, every new combination results in a new class.


    Decorator Pattern Solution.

    The Decorator pattern allows us to add a new behavior to an object using composition.
    In short:

    Still confused? Let's create code and be clear :)

    Step 1
    Create AbstractClassAbstractPlayer as

    publicabstractclassAbstractPlayer

    {

    publicabstractstringGetDescription();

    }

    Step 2

    Create Concrete Players as

    publicclassPlayer1:AbstractPlayer

    {

    publicoverridestringGetDescription()

    {

    return"Player Name:Player1";

    }

    }

    publicclassPlayer2:AbstractPlayer

    {

    publicoverridestringGetDescription()

    {

    return"Player Name:Player2";

    }

    }

    Step 3
    Create AbstractPlayerDecorator as

    publicabstractclassAbstractPlayerDecorator:AbstractPlayer

    {

    publicAbstractPlayerobjplayer;

    publicAbstractPlayerDecorator(AbstractPlayerobjplayer)

    {

    this.objplayer = objplayer;

    }

    }


    Step 4
    Create Concrete Decorators as

    publicclassGunDecorator : AbstractPlayerDecorator

    {

    publicGunDecorator(AbstractPlayer player)

    : base(player)

    {

    }

    publicoverridestringGetDescription()

    {

    returnthis.objplayer.GetDescription()+ "<BR>Payer has Equipped with Gun";

    }

    }

    publicclassKnifeDecorator: AbstractPlayerDecorator

    {

    publicKnifeDecorator(AbstractPlayer player)

    : base(player)

    {

    }

    publicoverridestringGetDescription()

    {

    returnthis.objplayer.GetDescription() + "<BR>Payer has Equipped with Knife";

    }

    }


    Step 5
    Write the following Client Code:

    AbstractPlayerobjPlayer = null;

    if(RdbPlayer1.Checked)

    {

    objPlayer = newPlayer1();

    }

    else

    {

    objPlayer = newPlayer2();

    }

    if(ChkGun.Checked)

    {

    objPlayer=newGunDecorator(objPlayer);

    }

    if(ChkKnife.Checked)

    {

    objPlayer=newKnifeDecorator(objPlayer);

    }

    Response.Write(objPlayer.GetDescription());


    Note: we use inheritance to do the type matching and composition to acquire new behavior.

    Class Diagram


    class-diagram-Decorator-Pattern.jpg


    Hope you enjoyed reading this article.

    Queries, Feedbacks and suggestions are always welcome.

    For more Design Patterns and .NET stuff do visit us.