Home > Design Patterns, dotnet 4, SOLID > Decorator Pattern

Decorator Pattern

Continuing with my post with design patterns today I am going to talk about another useful design pattern called thedecorator pattern. This pattern like the Adapter pattern is very simple and quite useful. Lets see the definition of decorator pattern in wikipedia.

  In object-oriented programming, the decorator pattern is a design pattern that allows   new/additional behavior to be added to an existing object dynamically.

That’s pretty good as we are always trying to build software which are loosely coupled, highly extensible and flexible and this pattern will help us a lot in achieving our goals.

As usual we will start with a UML class diagram then we will understand what role each class in the pattern and then start writing some code

Decorator Pattern UML Class Diagram

And the role of each classes in this pattern are:

  • Component: This is the class which defines the interface to which we want to add behavior.
  • Concrete Component:: The actual class which implements the interface and has the attribute to which we want to add more behavior/decorators.
  • Decorator: The class which acts as glue between the concrete component and the behavior.
  • Concrete Decorator: The actual decorator which adds that behavior.

Well you might be wondering what the heck it all means and how I am going to build something which has a decorator pattern in it. Well lets start with a domain problem, lets say you have Product Repository class which brings a list of Products and lets see how it all looks in the class diagram.

A Product Repository class diagram

No surprises there and lets see the code before we start re factoring and implementing the decorator pattern.

IProductRepository.cs

namespace NoPattern
{
    public interface IProductRepository
    {
        IEnumerable<Product> GetAll();
    }
}

Product.cs

namespace NoPattern
{
    public class Product
    {
        public int Id { get; set; }
        public String Name { get; set; }
        public string Description { get; set; }
        public decimal Price { get; set; }
    }
}

ProductService.cs

namespace NoPattern
{
    public class ProductService
    {
        private IProductRepository _productRepository;

        public ProductService(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }

        public IEnumerable<Product> GetAll()
        {
            var products = _productRepository.GetAll();
            return products;
        }
    }
}

Well looks pretty good and does it jobs we have nice separation of concern (SOC) and good interface dependencies and constructor injection, all in all simple and easy code. But lets say one of the requirements by the business is that the price of the product must apply some discount and also an exchange rate needs to be applied for selling the product on other countries. At this point you might say lets modify the ProductRepository class and add that.But doing this you are violating the Open/Close principle of the SOLID principles and really it is not your repository class responsibility to handle this.

Well then you might say we will change it through a stored procedure to do that and which is not a good idea as we are seeing the trend is moving more towards Domain Driven Development and we don’t want to go backwards.

Lets break down the problem so that we can find a better solution, as we know that Product class has got some attributes and most of them are straight forward and may have one to one representation in terms of the data and how it is persisted,however it’s one attribute which is Price which needs some sort of behaviour or decoration depending on certain conditions.

That’s a good start and in order to add flexibility we convert this into an interface. If you remember some of my design patterns blogs one of the easiest way to club up disparate objects or behaviour is using an interface.

So lets define a simple interface IPrice which encapsulates the Price/Cost attribute of the Product class.

IPrice.cs

namespace DecoratorPattern
{
    public interface IPrice
    {
        Decimal Cost { get;set; }
    }
}

So what we are saying with this interface is that as long as there are classes which implement this interface can act and change (decorate) this property . I know this sounds a bit confusing and time to see some more code to understand the bigger picture. First I will show you how the Product class looks like.

Product.cs

namespace DecoratorPattern
{
    public class Product
    {
        public int Id;
        public String Name;
        public string Description;

        public IPrice Price { get; set; }
       
    }
}

This is the moment where you can see rather than just writing some code we are moving more into engineering a solution. So here in the product class we have created a hook for this interface so that we can latch other classes which have the same interface and it’s these other classes(the decorators) which can change/manipulate the attribute or the behaviour. Lets see how is that achievable in code.

CurrencyPriceDecorator.cs

namespace DecoratorPattern
{
    public class CurrencyPriceDecorator : IPrice
    {
        private IPrice _basePrice;
        private decimal _exchangeRate;

        public CurrencyPriceDecorator(IPrice price,decimal exchangeRate)
        {
            _basePrice = price;
            _exchangeRate = exchangeRate;
        }

        public decimal Cost
        {
            get { return _basePrice.Cost * _exchangeRate; }
            set { _basePrice.Cost= value; }
        }
    }
}

 

TradeDiscountPriceDecorator.cs

namespace DecoratorPattern
{
    public class TradeDiscountPriceDecorator : IPrice
    {
        private IPrice _basePrice;

        public TradeDiscountPriceDecorator(IPrice iPrice)
        {
            _basePrice = iPrice;
        }

        public decimal Cost
        {
            get { return _basePrice.Cost * 0.95m; }
            set { _basePrice.Cost = value; }
        }
    }
}

Wow this looks cool as you can see we are getting nice code and good separation of concerns.Of course I have hard corded some of the mathematical calculation for easy illustration and can be easily wrapped with the strategy pattern to apply what kind of calculation(strategy) to apply for which class.

Anyway so far looks good and lets see how we are going to create the decoration code and as most of you have guessed it right it is using the extension method, in fact you can easily say that extension method is .NET’s implementation of decorator pattern from a framework point of view .

ProductDecoratorExtension.cs

namespace DecoratorPattern
{
    public static class ProductDecoratorExtension
    {
        public static void ApplyCurrencyMultiplier(this IEnumerable<Product> products)
        {
            foreach (var p in products)
            {
                p.Price = new CurrencyPriceDecorator(p.Price, .95m);
            }
        }

        public static void ApplyTradeDiscount(this IEnumerable<Product> products)
        {
            foreach (var p in products)
            {
                p.Price = new TradeDiscountPriceDecorator(p.Price);
            }
        }
    }
}

As you can see each of these class are well defined and they are following the SOLID principles with use of Single Responsibility Principle and Open/Close Principle.Now lets build the final piece of the puzzle that is the new and improved ProductService class which will still call the same ProductRepository class to get the list of products and then simple decorate it with the two define decorators and will apply the behavior.

ProductService.cs

namespace DecoratorPattern
{
    public class ProductService
    {
        private IProductRepository _productRepository;

        public ProductService(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }

        public IEnumerable<Product> GetAll()
        {
            var products = _productRepository.GetAll();

            products.ApplyCurrencyMultiplier(); // Decorate with Currency Multiplier
            products.ApplyTradeDiscount(); // Decorate with Trade Discount
            return products;
        }
    }
}

Lets write a simple unit test to see how we will call the method in the Product Service class.

Unit Test

namespace DecoratorPattern.Test
{
    [TestClass()]
    public class When_testing_product_service
    {
        [TestMethod()]
        public void Should_be_able_to_get_products_using_the_decorators()
        {
            IProductRepository productRepository = new FakeProductRepository();
            ProductService target = new ProductService(productRepository);
            int expected = 2;
            int result = 0;
            IEnumerable<Product> actual = target.GetAll();
            foreach(var p in actual)
            {
                result++;
            }
            Assert.AreEqual(expected,result );
         }
    }
}

I know I am a bit guilty here for not writing a good test, ideally I should assign the base price for all the products as some multiple of 10s and see each of the price being return as some percentage of the value due to the discount and exchange rate but I hope the TDD guys will spare me as it’s more about the decorator pattern.

And now if you look at the final implementation in VS class diagram you will see how close it is to the initial UML diagram in the beginning.

Decorator pattern implementation diagram in VS

Sideline note:-I have been trying to complete this blog for the last three days and learned my lesson that watching comedy movies and writing blog doesn’t play that well πŸ™‚

Advertisements
  1. Yogesh
    February 17, 2011 at 3:19 am

    One of your favourite patterns. Good stuff once again.

  2. February 17, 2011 at 8:06 pm

    Yogesh :

    One of your favourite patterns. Good stuff once again.

    Thanks yogesh I hope you are enjoying the pattern series after the SOLID series and hope you will share your knowledge and experience with these patterns some day πŸ™‚

    Cheers !!!

  3. Yogesh
    February 17, 2011 at 10:13 pm

    Yes Prashant I would love to share my 2c to the design patterns world. I have a great many ideas on sharing the integration patterns but need to find the time for that effort. Your SOLID series of design patterns is surely second only to the great Mr. Fowler. So you done really well and has motivated me for sure.

    Keep it going.

  4. June 24, 2011 at 7:30 am

    You could further extend this example by extracting the algorithms used to determine the price. This would result in a nice combination of the decorator – and strategy pattern.
    You could, ofcourse, also leave this as an exercice to the reader πŸ˜‰

    • June 24, 2011 at 10:04 am

      Hi Arnold,
      You are spot on that and I did blog about the strategy pattern just before this blog post and it’s up to the readers to combine them and use them. The idea is inspire and help people to write good clean code. I hope you will enjoy my rest of the post and give me your ideas and vision into “Design Patterns” πŸ™‚

  1. July 19, 2011 at 9:10 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: