Decorator Design Pattern in C#

Decorator Design Pattern in C# with Examples

In this article, I am going to discuss the Decorator Design Pattern in C# with some examples. Please read our previous article where we discussed the Facade Design Pattern in C# with examples. The Decorator Design Pattern falls under the category of Structural Design Pattern. As part of this article, we are going to discuss the following pointers.

  1. What is the Decorator Design Pattern?
  2. Understanding the Decorator Design Pattern with an example
  3. Implementing Decorator Design Pattern in C#
  4. When to use the Decorator Design Pattern?
What is the Decorator Design Pattern in C#?

The Decorator Design Pattern allows us to dynamically add new functionalities to an existing object without modifying its structure. So, we can say that the Decorator Design Pattern provides an alternative approach to inheritance for modifying the behavior of an object. When we use inheritance to extend the behavior of a class, then this takes place at compile time.

This design pattern creates a decorator class which wraps the original class and then add the additional functionalities keeping class signature intact. So, this design pattern works just like a wrapper to an existing class.

Understanding the Decorator Design Pattern in C# with an example:

Let say we have an interface called ICar and two classes BMW and Suzuki implementing the ICar interface as shown below.

Decorator Design Pattern in C#

Now our requirement is to add a new functionality i.e. DiscountedPrice without changing the structure above three classes. Let see the step by step procedure to implement the Decorator Design Pattern in C# with one example.

Implementing Decorator Design Pattern in C#:

We are going to implement a Car interface and concrete classes implementing the Car interfaces. We will then create an abstract car decorator class called CarDecorator implementing the Car interface and having the Car object as its instance variable. Then we will create a class called DiscountedDecorator concrete class by implementing the abstract CarDecorator class.

Step1: Create an interface ICar.cs

Create a class file with the name ICar.cs and then copy and paste the following code in it.

namespace DecoratorDesignPattern
{
    public interface ICar
    {
        void ShowBasicDetails();
        double Price();
    }
}
Step2: Create Concrete classes implementing the ICar interface.

Create a class file with the name BMW.cs and then copy and paste the following code in it.

using System;
namespace DecoratorDesignPattern
{
    public class BMW : ICar
    {
        public double Price()
        {
            return 100000;
        }

        public void ShowBasicDetails()
        {
            Console.WriteLine("Name : " + "BMW");
            Console.WriteLine("Model No : " + "BMW-1234");
        }
    }
}

Create another class file with the name Suzuki.cs and then copy and paste the following code in it.

using System;
namespace DecoratorDesignPattern
{
    public class Suzuki : ICar
    {
        public double Price()
        {
            return 300000;
        }

        public void ShowBasicDetails()
        {
            Console.WriteLine("Name : " + "Suzuki");
            Console.WriteLine("Model No : " + "Suzuki-6789");
        }
    }
}
Step3: Create an abstract decorator class implementing the ICar interface.

Create a class file with the name CarDecorator.cs and then copy and paste the following code in it.

namespace DecoratorDesignPattern
{
    public abstract class CarDecorator : ICar
    {
        private ICar car;

        public CarDecorator(ICar _car)
        {
            car = _car;
        }

        public double Price()
        {
           return car.Price();
        }

        public void ShowBasicDetails()
        {
            car.ShowBasicDetails();
        }
    }
}

We kept this class as abstract, so it will not possible to create an instance of this class. It is used just as a wrapper and it does not add any new functionality into the Car class. Also, we have implemented the Price and ShowBasicDetails method.

Step4: Create concrete decorator class implementing the abstract CarDecorator class

Create a class file with the name DiscountedDecorator.cs and then copy and paste the following code in it.

using System;
namespace DecoratorDesignPattern
{
    public class DiscountedDecorator : CarDecorator
    {
        public DiscountedDecorator(ICar car) : base(car) { }

        public void DiscountedPrice()
        {
            Console.WriteLine("Discounted Price :" + .10 * base.Price());
        }
    }
}
Step5: Use the DiscountedDecorator to decorate the Car object.

Please modify the Main method of Program class as shown below.

using System;
namespace DecoratorDesignPattern
{
    class Program
    {
        static void Main()
        {
            ICar bmwCar = new BMW();
            bmwCar.ShowBasicDetails();

            DiscountedDecorator decorator1 = new DiscountedDecorator(bmwCar);
            decorator1.DiscountedPrice();

            ICar suzukiCar = new Suzuki();
            suzukiCar.ShowBasicDetails();

            DiscountedDecorator decorator2 = new DiscountedDecorator(suzukiCar);
            decorator2.DiscountedPrice();

            Console.Read();
        }
    }
}

Output:

Decorator Design Pattern in C# with Examples

As you can see, here we have not changed the Core classes i.e. ICar, BMW, and Suzuki. By creating the wrapper and decorator classes, we have dynamically added new behavior to ICar, BMW, and Suzuki.

When to use the Decorator Design Pattern?

We need to use the Decorator Design Pattern in C# when 

  1. We need to add new functionalities to existing objects dynamically,  
  2. The class definition may be hidden or otherwise unavailable for subclassing.  

In the next article, I am going to discuss the Bridge Design Pattern in C# with some examples. Here, in this article, I try to explain the Decorator Design Pattern in C# step by step with some simple examples. I hope you understood the need and use of Facade Design Pattern in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *