Design Patterns : Decorator

Design Patterns : Decorator

Learn design patterns in C# : docorator design pattern

In this tutorial, we will look at the abstract factory design pattern, and we will have a detailed example of how to use this design pattern using the C# language.
All you need to follow along with this article is some knowledge of the C# language, object-oriented programming and to have Visual Studio installed.

What is Decorator Design Pattern :

The decorator design pattern aims at adding new functionality to an existing object without modifying it or changing the definition of the object. The goal is to add new responsibilities to an instance of an object.

The participants

The classes and objects participating in this pattern include:

  • The component or the base interface

    • defines the interface for objects that can have responsibilities added to them dynamically.
  • ConcreteComponent

    • defines an object to which additional responsibilities can be attached.
  • Decorator

    • maintains a reference to a Component object and defines an interface that conforms to the Component's interface.
  • ConcreteDecorator

    • adds responsibilities to the component.

A Simple Example:

Now, let's create a simple application where we create a Pizza and then add functionalities to it.

Base Interface

Now, let's create the base interface which is an IPizza, this abstract component has the functionGetPizzaType():

// Base Interface
interface IPizza
{
    string GetPizzaType();
}

Concrete implementation

Now, let's create an implementation of the previous Interface:

// Concrete Implementation
class Pizza : IPizza
{
    public string GetPizzaType()
    {
        return "This is a normal pizza";
    }
}

Concrete Decorators

Now, let's create the first concrete decorator which is CheeseDecorator :

// Concrete decorators
class CheeseDecorator : IPizza
{
    private IPizza _pizza;
    public CheeseDecorator(IPizza pizza) { _pizza = pizza; }
    public string GetPizzaType()
    {
        //string type = base.GetPizzaType();
        var type = _pizza.GetPizzaType();
        type += " with cheese";
        return type;
    }
}

Now, let's create the second concrete decorator which is TomatoDecorator :

class TomatoDecorator : IPizza
{
    private IPizza _pizza;
    public TomatoDecorator(IPizza pizza) { _pizza = pizza; }
    public string GetPizzaType()
    {
        string type = _pizza.GetPizzaType();
        type += " with tomato";
        return type;
    }
}

The whole code

Now, let's put it all together with the main function:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DecoratorDP
{
    // Decorator design pattern
    internal class Program
    {
        static void Main(string[] args)
        {
            IPizza pizza = new Pizza();
            IPizza cheesePizza = new CheeseDecorator(pizza);
            IPizza tomatoPizza = new TomatoDecorator(pizza);

            Console.WriteLine(cheesePizza.GetPizzaType());
            Console.WriteLine(tomatoPizza.GetPizzaType());
            Console.Read();
        }
    }

    // Base Interface
    interface IPizza
    {
        string GetPizzaType();
    }

    // Concrete Implementation
    class Pizza : IPizza
    {
        public string GetPizzaType()
        {
            return "This is a normal pizza";
        }
    }



    // Concrete decorators
    class CheeseDecorator : IPizza
    {
        private IPizza _pizza;
        public CheeseDecorator(IPizza pizza) { _pizza = pizza; }
        public string GetPizzaType()
        {
            //string type = base.GetPizzaType();
            var type = _pizza.GetPizzaType();
            type += " with cheese";
            return type;
        }
    }

    class TomatoDecorator : IPizza
    {
        private IPizza _pizza;
        public TomatoDecorator(IPizza pizza) { _pizza = pizza; }
        public string GetPizzaType()
        {
            string type = _pizza.GetPizzaType();
            type += " with tomato";
            return type;
        }
    }
}

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Twitter

Did you find this article valuable?

Support Interrupt101 by becoming a sponsor. Any amount is appreciated!