Pranay Rana: How and Where Decorator Design Pattern

Sunday, February 1, 2015

How and Where Decorator Design Pattern

Decorator Design Pattern

Decorator design pattern is one of the behaviour pattern introduced by GOF. Decorator design pattern is used during development to provide extra functionality to existing Types. So Decorator Design pattern allow developer to achieve rule of SOLID rules
  1. Single Responsibility Principle – Class/Function should do only one task or Class/ Function should have only one reason to change. 
  2. Open Close Principle – Class/Function open for extension but close for modification.
  3. Liskov Substitution type – If type S is derived from Type T than , object of Type T can replace object of Type S.
Decorator means decor basic element to achieve extra functionality. Below image is one of the presentations of decoration


Image shows gift with the basic box and other image is decoration on gift with good wrapping. Extra functionality achieved over here is good look on the basic gift with the help of wrapping decoration.

Simple Example of Design Pattern

Below image shows the class diagram of basic decorator design pattern



  • IBasicService - Basic contract that need to be implemented by derived types.
  • BasicServiceImplementation – Its basic/concreate implementation which is derived from interface, as it basic its provides basic functionality.
  • Decorator1OnBasic & Decorator2OnBasic – its decorated implementation which is derived from interface. It’s actually providing extra functionality over basic implementation.
  • Client – make use of the concreate implementation, it creates instance of Decorate and use functionality of it. Code below is implementation of the Decorator design pattern and Class diagram discussed above.
namespace BasicDecoratorPattern
{
    public interface IBaseService
    {
        void Print();
    }

    public class BasicServiceImplementaion : IBaseService
    {
        public void Print()
        {
            Console.WriteLine("Basic Item");
        }
    }

    public class Decorator1OnBasic : IBaseService
    {
        private readonly IBaseService BasicRealTimeService;
        public Decorator1OnBasic(IBaseService service)
        {
            BasicRealTimeService = service;
        }

        public void Print()
        {
            BasicRealTimeService.Print();
            Console.WriteLine("Extra functionality from Decorator ONE");
        }
    }

    public class Decorator2OnBasic : IBaseService
    {
        private readonly IBaseService BasicRealTimeService;
        public Decorator2OnBasic(IBaseService service)
        {
            BasicRealTimeService = service;
        }

        public void Print()
        {
            BasicRealTimeService.Print();
            Console.WriteLine("Extra functionality from Decorator SECOND");
        }
    }

    public class Client
    {
        public Client()
        {
            IBaseService realTimeService = new BasicServiceImplementaion();

            IBaseService basicRealTimeServiceDecorator1 = new Decorator1OnBasic(realTimeService);
            IBaseService basicRealTimeServiceDecorator2 = new Decorator2OnBasic(realTimeService);

            basicRealTimeServiceDecorator1.Print();
            basicRealTimeServiceDecorator2.Print();
        }
    }
}

Points to remember in above code implementation
  1. DecoratorOnBaisc take IBasicService instance as input to create instance of decorator class.
  2. Client create instance of BasicServiceImplementation first and pass that instance to the decorator.
  3. Decorator make use of the basic implementation instance passed as argument to it to achieve basic functionality and extra functionality by decorating it.
Output
Output shows that decorator add extra functionality over the basic functionality. To understand more below is one more example of decorator pattern in real world.

Real-World Example of Design Pattern

Below is class diagram of Real-World design pattern, Below class diagram represent different kind i.e. different kind of the Milkshake (Mango & Chocolate) over basic Milkshake.


Mapping with Basic Implementation
  • IMilkShake is equals to IBasicService
  • MilkShake is equeal to BasicImplementation.
  • MangoMilshake & ChoclateMilkShake is equal to Decorator1OnBasic & Decorator2OnBasic.
Note in this implementation MilshakeDecorator is abastract class which is derived from the IMilkShake and Decorator of the MilkShake is derived from this decorator class. There are some common functionality so this class is created but it doesn’t affect actual implementation of Decorator pattern.

namespace RealWorldDecoratorPattern
{
    public interface IMilkShake
    {
        string Serve();
        int Price();
    }

    public class MilkShake : IMilkShake
    {
        public string Serve()
        {
            return "MilkShake";
        }

        public int Price()
        {
            return 30;
        }
    }

    public abstract class MilkshakeDecorator : IMilkShake
    {
        public readonly IMilkShake Milkshake;
        public MilkshakeDecorator(IMilkShake milkShake)
        {
            Milkshake = milkShake;
        }
        public string Flavour { get; set; }
        public int FlavourPrice { get; set; }

        public abstract string Serve();
        public abstract int Price();

    }

    public class MangoMilkShake : MilkshakeDecorator
    {
        public MangoMilkShake(IMilkShake milkShake)
            : base(milkShake)
        {
            this.Flavour = "Mango";
            this.FlavourPrice = 10; 
        }

        public override string Serve()
        {
            return  "Serving " + this.Flavour + " " + Milkshake.Serve();
        }

        public override int Price()
        {
            return  this.FlavourPrice  + Milkshake.Price();
        }
    }

    public class ChoclateMilkShake : MilkshakeDecorator
    {
        public ChoclateMilkShake(IMilkShake milkShake)
            : base(milkShake)
        {
            this.Flavour = "Choclate";
            this.FlavourPrice = 20;
        }

        public override string Serve()
        {
            return "Serving "  + this.Flavour + " " + Milkshake.Serve();
        }

        public override int Price()
        {
            return this.FlavourPrice + Milkshake.Price();
        }
    }

    public class Client
    {
        public Client()
        {
            IMilkShake milkShake = new MilkShake();

            IMilkShake mangoMilkshake = new MangoMilkShake(milkShake);
            IMilkShake choclateMilkshake = new ChoclateMilkShake(milkShake);

            Console.WriteLine(mangoMilkshake.Serve());
            Console.WriteLine(mangoMilkshake.Price());

            Console.WriteLine();

            Console.WriteLine(choclateMilkshake.Serve());
            Console.WriteLine(choclateMilkshake.Price());
        }
    }

}

Output

In above code MilkShake Decorator class (Mango and Chocolate) make use of bas Mikshake class. Decorator class provide decoration on the Basic Milkshake class and provide output by using basic implement and extra functionality.

Use of Design Pattern in Application

Above two example helps to understand Decorator design pattern Basic and RealWorld problem. But in this section is help you to understand how to user Design pattern in Application i.e. where developer can possibly use it in Application.

Decorator design pattern it very helpful to achieve cross cutting concern/Aspect oriented programming concepts like
  1. Authentication
  2. Authorization
  3. Logging
  4. Caching
  5. Validation
  6. Exception Management
Apart from Cross cutting concern as explain before it can be used to decorate class with extra added functionality i.e. it not always true that you can use decorator pattern just to achieve cross cutting concern.

Below is Class diagram of the achieving Caching Cross Cutting Concern with the CachingDecorator.

  • IProvides is equal to IBasicService – for this example its contract which is having GetProviderList.
  • Provider is equal to BasicServiceImplementation – for this example is concrete implementation and used to get list of providers.
  • CacheProvider is equal to DecoratorOnBasic – for this example this is decorator which does task of caching fetched providers and when requested it provide cache data or if cache data is not available than it request fresh data from Provider (basic) implementation.
namespace CacheDecoratorPattern
{
    public interface IProviders
    {
        NameValueCollection GetProviderList();
    }

    public class Providers : IProviders
    {
        public NameValueCollection GetProviderList()
        {
            NameValueCollection providerList = new NameValueCollection();
            providerList.Add("SQL", "SQLProvider");
            providerList.Add("Oracle", "OracleProvider");
            providerList.Add("MySQL", "MyProvider");
            return providerList;
        }
    }

    public class CacheProvider : IProviders
    {
        private readonly IProviders provider;

        private NameValueCollection CachedProviderList;

        public CacheProvider(IProviders provider)
        {
            this.provider = provider;
        }

        public NameValueCollection GetProviderList()
        {
            if(CachedProviderList == null)
                CachedProviderList = provider.GetProviderList();

            return CachedProviderList;
        }
    }

    public class Client
    {
        public Client()
        {
            IProviders provider = new Providers();
            CacheProvider cacheProvider = new CacheProvider(provider);

            var providerlist = cacheProvider.GetProviderList();
        }
    }
}

In code CachProvider is class which is decorator over Provider class and take IProvider as input to it. As it just example right now cache value stored in private variable of CacheProvider but in real application this can be replace by real caching i.e. it can be web application cache class or Enterprise application library cache block.

Decorator with Dependency injection Container

Below is just example code to register decorator instance with the Microsoft Unity container Register Decorator

var container = new UnityContainer();
  container.RegisterType(
      typeof( IProvider ),
      typeof( Provider ),
      "BasicProvider"
  );
  contract.RegisterType(
      typeof( IProvider ),
      typeof( CacheProvider ),
     new InjectionConstructor(
         new ResolvedParameter(
             typeof( IProvider ),
             "BasicProvider"
         )
     )
 );

So once it gets register, with Resolve method of container one can easily get instance of the Decorator.

var contract = container.Resolve<IProvider>();

At the End Achieved SOLID principle

Single Responsibility Principle – As in the example Basic implementation Provider does task which it is responsible for example – fetching data in last example. And the decorator is responsible for doing extra functionality like CacheProvider does task for caching data not task of getting data.

Open Close Principle - As rule states here Basic implementation Provider is close for the modification but open for extension that achieved through CachProvider which extends functionality of basic implementation.

Liksov Subtitution Principle – As rule sates here Basic implementation Provider object replaced by the parent type IProvider interface in Decorator constructor where Provider object injected by client class.

Note:
This is my point of view regarding pattern. Please provide your feedback regarding it and also provide feedback it something you find wrong in this.

1 comment: