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 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 Decorator Design Pattern?
  2. Understanding the Decorator Design Pattern with Real-Time Examples.
  3. Implementing Decorator Design Pattern in C#
  4. Understanding the Class Diagram of Decorator Design Pattern.
  5. When to use the Decorator Design Pattern in Real-Time Applications?
What is the Decorator Design Pattern in C#?

The Decorator Design Pattern in C# allows us to dynamically add new functionalities to an existing object without altering or modifying its structure and this design pattern acts as a wrapper to the existing class. That means Decorator Design Pattern dynamically changes the functionality of an object at runtime without impacting the existing functionality of the object. In short, this design pattern adds additional functionalities to the object by wrapping it. A decorator is an object that adds features to another object.

Understanding Decorator Design Pattern with an Example in C#

Let us understand the Decorator Design Pattern in C# with an Example. Please have a look at the following image. As shown in the below image, we have a circle object and that circle object is having a method called Draw. What the Draw method will do is it will draw a circle.

What is the Decorator Design Pattern in C#

Now I want to add some color to the circle object but I don’t want to change or alter the structure of the Circle object. Meaning I am not allowed to add any method to the Circle object or not allowed to change the existing Draw method body. So, how can I achieve this? I can achieve this very easily using the Decorator Design Pattern in C#. So what I can do here is, I will introduce the CircleDecorator object which will wrap the Circle object as shown in the below image. The CircleDecorator object also has the Draw method. What the CircleDecorator Draw method will do is, first it will call the Draw method of the Circle object so that it will draw the circle and then it will call the SetColor method of the CircleDecorator object to set the color of the circle.

Decorator Design Pattern in C# with Examples

So, in this way, without affecting the structure of the Circle object, we can add new functionalities to the Circle object. Now, if you read the definition again then you will understand what us Decorator Design Pattern is.

Note: The Decorator Design Pattern provides an alternative approach to inheritance for modifying the behavior of an object. If we use inheritance to extend the behavior of a class, then this takes place at compile time.

Real-Time Example of Decorator Design Pattern:

Let us understand the Decorator Design Pattern with one Real-Time Example. Please have a look at the following image. On the left-hand side, you can see the Car without any engine. Let’s say, I want to add either a Petrol engine or a Diesel engine to this car. Then what I need to do is, I have to introduce the CarDecorator. What this CarDecorator will do is, it will add an Engine to the Car. Let’s say I want to add a Petrol Engine then the CarDecorator will add the Petrol Engine to this car and return the car with a petrol engine to the client. Suppose, I want to add a Diesel Engine to this car, then the CarDecorator will add a Diesel engine to this car and return the car with the Diesel engine to the client.

Real-time Example of Decorator Design Pattern in C#

As per Decorator Design Pattern, the work of the decorator is to add new functionalities or behavior to an existing object without altering its structure. So, in this case, a Car without an engine is the existing object. What the CarDecorator does is, it will add a Petrol Engine or a Diesel Engine to the Car based on the requirement of the client. So, I think this is one of the best real-time examples of the Decorator Design Pattern.

Implementing the Decorator Design Pattern in C#:

Let us implement the above-discussed car example using the Decorator Design Pattern in C# step by step. Once we implement the decorator design pattern then we will try to understand the class diagram of the Decorator Design Pattern by comparing it to this example so that you can easily understand.

Step 1: Creating the Car interface

Create an interface with the name ICar.cs and then copy and paste the following code into it. This interface has one abstract method i.e. ManufactureCar and this method is going to be implemented by the Concrete Subclasses. The point that you need to remember is this interface defines the operations which can be altered by the decorators.

namespace DecoratorDesignPattern
{
    // This is the Base Component that defines operations that can be altered by decorators.
    public interface ICar
    {
        ICar ManufactureCar();
    }
}
Step 2: Creating Concrete Car

Create a class file with the name BMWCar.cs and then copy and paste the following code into it. This is a concrete class and implements the ICar interface i.e. provides the default implementation for the ManufactureCar method. What this ManufactureCar method will do is, it will manufacture Car Body, Door, Wheels, and Glass. So, when we call the ManufactureCar method it returns the BMW car but without an engine. Later as per the requirement of the client, we will add either a Petrol engine or Diesel Engine to this car.

namespace DecoratorDesignPattern
{
    // Concrete Components provide default implementations of the operations.
    // There might be several variations of these classes.
    public class BMWCar : ICar
    {
        private string CarName = "BMW";
        public string CarBody { get; set; }
        public string CarDoor { get; set; }
        public string CarWheels { get; set; }
        public string CarGlass { get; set; }
        public string Engine { get; set; }

        public override string ToString()
        {
            return "BMWCar [CarName=" + CarName + ", CarBody=" + CarBody + ", CarDoor=" + CarDoor + ", CarWheels="
                            + CarWheels + ", CarGlass=" + CarGlass + ", Engine=" + Engine + "]";
        }

        public ICar ManufactureCar()
        {
            CarBody = "carbon fiber material";
            CarDoor = "4 car doors";
            CarWheels = "6 car glasses";
            CarGlass = "4 MRF wheels";
            return this;
        }
    }
}
Step 3: Creating a Car Decorator

Create a class with the name CarDecorator.cs and then copy and paste the following code into it. This is going to be an abstract class and it also implements the ICar interface i.e. the ManufactureCar method. The point that you need to focus on is, here we are declaring one field and initializing that field using the class constructor. The existing car object which you want to decorate, that existing car object you need to pass as an argument to the constructor of this class. That existing car object which this class received through the constructor is going to be stored in the field that we created here i.e. protected ICar car; We also declare the ManufactureCar method as virtual which allows this method to be overridden by the child concrete decorator classes. The following code is self-explained, so please go through the comment lines.

namespace DecoratorDesignPattern
{
    // The Base Decorator class is also inherited from the same interface as the other Concrete Components inherited. 
    // The primary responsibility of this Base Decorator class is to define the wrapping interface for all concrete decorators. 
    // The default implementation of the wrapping code includes a field for storing a wrapped component and
    // we need to initialize that field. Here, we are initializing that field using the class constructor

    //Inherited from the Base Component Interface
    public abstract class CarDecorator : ICar
    {
        //Create a Field to store the Concrete Component
        protected ICar car;

        //Initializing the Field using Constructor
        //While Creating an instance of the CarDecorator (Instance of the Child Class that Implements CarDecorator abstract)
        //We need to pass the existing car object which we want to decorate
        public CarDecorator(ICar car)
        {
            //Store that existing car object in the car variable
            this.car = car;
        }

        //Providing Implementation for the Base Component Interface
        //Here, we are just calling the Concrete Component ManufactureCar method
        //We are making this Method Virtual to allow the Child Concrete Decorator class to override
        public virtual ICar ManufactureCar()
        {
            //Call the Existing Car Object ManufactureCar method to return the car without engine
            //Later in the Child class of this abstract we will see how to call this method 
            //and how to add an Engine
            return car.ManufactureCar();
        }
    }
}
Step4: Creating Diesel Car Decorator

Create a class file with the name DieselCarDecorator.cs and then copy and paste the following code into it. This is a concrete class, and this class is inherited from the CarDecorator abstract class. This class overrides the ManufactureCar method. What this ManufactureCar method will do is, it will add a diesel engine to the car and will return the BMW car with Diesel Engine. But within the ManufactureCar method, first, call the ManufactureCar method of the BMWCar object to build the car, and then add the Diesel Engine to the car by calling the AddEngine method.

using System;
namespace DecoratorDesignPattern
{
    //The following Concrete Decorator class will add Petrol Engine to the Existing Car
    class PetrolCarDecorator : CarDecorator
    {
        //Pass the existing car object while creating the Instance of PetrolCarDecorator class
        //Also pass the same existing pizza object to the base class constructor 
        //i.e. CarDecorator abstract class constructor
        public PetrolCarDecorator(ICar car) : base(car)
        {
        }

        //Overriding the ManufactureCar method to add Petrol Engine
        public override ICar ManufactureCar()
        {
            //First Call the Concrete Components ManufactureCar Method 
            car.ManufactureCar();
            //Then Add a Petrol Engine by calling the AddEngine Method
            AddEngine(car);
            return car;
        }

        public void AddEngine(ICar car)
        {
            if (car is BMWCar BMWCar)
            {
                BMWCar.Engine = "Petrol Engine";
                Console.WriteLine("PetrolCarDecorator added Petrol Engine to the Car : " + car);
            }
        }
    }
}
Step5: Creating Petrol Car Decorator

Create a class file with the name PetrolCarDecorator.cs and then copy and paste the following code into it. It is the same as the DieselCarDecorator. This means it is also inherited from the CarDecorator class and overrides the ManufactureCar method. The ManufactureCar method will add the Petrol engine to the car and it will return the BMW car with Petrol Engine. But within the ManufactureCar method, first, call the ManufactureCar method of the BMWCar object to build the car, and will add the Diesel Engine to the car by calling the AddEngine method.

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

        public override ICar ManufactureCar()
        {
            car.ManufactureCar();
            AddEngine(car);
            return car;
        }

        public void AddEngine(ICar car)
        {
            if (car is BMWCar BMWCar)
            {
                BMWCar.Engine = "Petrol Engine";
                Console.WriteLine("PetrolCarDecorator added Petrol Engine to the Car : " + car);
            }
        }
    }
}
Step6: Client code

In our example, the Main method of the Program class is nothing but the client code. So, please modify the Main method of the Program class as shown below. Here, first, we create an object of BMWCar and then call the ManufactureCar method which will create the car without an engine. Then we create the instance of DieselCarDecorator and pass the BMWCar instance as a parameter to the constructor of DieselCarDecorator class. And when we call the ManufactureCar method of the DieselCarDecorator instance, then it will add Diesel Engine to the Car. And the process is the same for manufacturing a car with a Petrol Engine.

using System;
namespace DecoratorDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            //Create an instance of Concrete Component BMWCar
            ICar bmwCar1 = new BMWCar();
            //Calling the ManufactureCar method will create the BMWCar without an engine
            bmwCar1.ManufactureCar();
            Console.WriteLine(bmwCar1 + "\n");

            //Adding Diesel Engine to the bmwCar1
            //Create an instance DieselCarDecorator class and 
            //pass existing bmwCar1 as an argument to the Constructor which we want to decorate
            DieselCarDecorator carWithDieselEngine = new DieselCarDecorator(bmwCar1);
            //Calling the ManufactureCar method on the carWithDieselEngine object will add Diesel Engine to the bmwCar1 car
            carWithDieselEngine.ManufactureCar();

            Console.WriteLine();
            //The Process is the same for adding Petrol Engine to the existing Car
            ICar bmwCar2 = new BMWCar();
            PetrolCarDecorator carWithPetrolEngine = new PetrolCarDecorator(bmwCar2);
            carWithPetrolEngine.ManufactureCar();

            Console.ReadKey();
        }
    }
}
Output:

How to implement the Decorator Design Pattern in C#

Now I hope you understand the Decorator Design Pattern in C#. So, let’s try to understand the class diagram (UML Diagram) and the different components or participants involved in the Decorator Design Pattern by comparing it with our example.

Understanding the Class Diagram or UML Diagram of the Decorator Design Pattern:

Let us understand the Class Diagram or UML Diagram of the Decorator Design Pattern. Please have a look at the following image.

UML Diagram of Decorator Design Pattern

At the top, you can see the ICar interface and it has the ManufactureCar method. This interface is implemented by the BMWCar concrete class and provides the implementation for the ManufactureCar method. So, when we call the ManufactureCar method on the BMWCar object it will return BMWCar without the Engine to the caller.

The CarDecorator is an abstract class and it also implements the ICar interface. It has Constructor and to the constructor, we need to pass the BMWCar object which we want to decorate i.e. we want to add the engine.

The CarDecorator abstract class is extended to two concrete classes i.e. DieselCarDecorator and PetrolCarDecorator. Both this class overrides the ManufactureCar method. The DieselCarDecorator will add Diesel Engine to the BMWCar and return the BMWCar with Diesel Engine to the caller. Similarly, the PetrolCarDecorator will add Petrol Engine to the BMWCar and return BMWCar with Petrol Engine to the caller.

Components of Decorator Design Pattern

As shown in the UML Diagram, four components are involved in the Decorator Design Pattern. They are as follows:

  1. Component: This is an interface. In our example, it is the ICar interface. This interface contains members that are going to be implemented by the concrete component (in our example BMWCar) classes and decorator (in our example CarDecorator) classes.
  2. Concrete Component: This is going to be a concrete class. In our example, it is the BMWCar class. This class simply implements the Component interface. You can see, in our example, BMWCar class implements the ICar interface and provide implementations for the ManufactureCar method.
  3. Decorator: This is an abstract class and in our example, it is the CarDecorator class. This class implements the Component (i.e. ICar) interface and contains a reference to a component instance (in our example it is the car variable). This class also acts as the base class for all decorators. It has a Constructor and to the constructor, we need to pass the car object which we want to decorate i.e. we want to add the engine.
  4. ConcreteDecoratorA / ConcreteDecoratorB: These are concrete classes (in our example, it is the PetrolCarDecorator and DieselCarDecorator classes) and inherited from the Decorator (i.e. CarDecorator) abstract class. This class adds additional responsibility (in our example adding an engine) to the original component by overriding the ManufactureCar method.
When to use the Decorator Design Pattern in real-time applications?

We need to use the Decorator Design Pattern Real-Time Applications when 

  1. We want to add new functionalities to existing objects dynamically,  
  2. A class definition may be hidden or otherwise unavailable for subclasses.  

In the next article, I am going to discuss the Decorator Design Pattern Real-Time Example – Pizza using C#. Here, in this article, I try to explain the Decorator Design Pattern in C# with Examples. I hope you understood the need and use of the Decorator Design Pattern in C# with Examples.

4 thoughts on “Decorator Design Pattern in C#”

  1. blank

    Is the method ManufatureCar not misreading?
    I had to scroll up to check whether the class is a FactoryPattern or just a car.
    If the decorator passes the same instance, why don’t you make a new method such as UpgradeCar?

  2. blank

    As far as I understood, bmwCar1 and carWithDieselEngine are pointing the same instance.
    In this case, should we remove one of the reference? Or is it not a big deal?

Leave a Reply

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