Overview of Decorator Pattern in C#

Pattern

"Design Patterns are general, repeatable solutions to common recurring problems in software development."

A "pattern" has been defined as "an idea that has been useful in one practical context and will probably be useful in others".

A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations. Object-oriented design patterns typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved.

In this article I'll try to share my thoughts of one of Structural Design Pattern named Decorator.

Structural Design Patterns are concerned with how classes and objects are combined to form larger structures.

Let's jump into this and try to swim.

Definition

The Gang Of Four (GOF) defines the Decorator pattern as "Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality."

Closed for Modification and Open for Extension

One of the main challenges we encounter in development is change. The Closed for Modification and Open for Extension principle says a new functionality can be added by keeping the original code unchanged. To explore more on this kindly visit: The Open Closed Principle of SOLID

In our applications we occasionally create an object with some basic requirements and later we'd like to add some more functionality to this object dynamically with additional subclasses, in that scenario we use the Decorator Pattern.

Let's assume we have an object that saves a stream in a Comma Separated Value (CSV) format. Later we need to add more behavior to the same object to save that stream in a bit more secure format like a PDF with a password.

Here is the class diagram of the Decorator depicted below:

DecoratorPatt1.jpg

Participants

The classes and/or objects participating in this pattern are:

  • Component (Pizza)
    • Defines the interface for objects that can have responsibilities added to them dynamically.
  • ConcreteComponent (ThinCrust,ThikCrust)
    • Defines an object to which additional responsibilities can be attached.
  • Decorator (Decorator)
    • This defines the interface for all the dynamic functionalities that can be added to the reference to a ConcreateComponent.
  • ConcreteDecorator (OnionPizzaDecorator, CheezPizzaDecorator,)
    • Adds responsibilities to the component.
     

To understand the decorator pattern let us extend the example being used here. We have a Pizza class as a base class. Later we may add more stuff, like toppings on each Pizza, for example extra cheeze, Onions and Jalapeno with Baby Corn.

I have chosen a very simple example (Pizza) because most people would be familiar with this. Though there could be the same scenario for other objects like for Ice Cream and Coffee.

Let us start by creating the component class.

public abstract class Pizza
{
     public abstract double GetPrice();
}

Here is the ConcreateConponent class defines the functionality of the base class Pizza.
 

class ThikCrust : Pizza

{

    private double p_Price = 250.0;

 

    public override double GetPrice()

    {

        return p_Price;

    }

}

 

class ThinCrust : Pizza

{

    private double p_Price = 200.0;

 

    public override double GetPrice()

    {

        return p_Price;

    }

}

We are done with the ConcreateConponent and ready for our base object. Now we need to add additional functionality to the base Pizza like the toppings, cheeze and other extra stuff. Let's create a Decorator Class. The main advantages of the decorator is to continue the use of the original class.

Because there may be many reasons to change the class.

Conclusion on Change

So basically we can conclude that whenever changes are required, the possible solutions could be:

  • Change the original class

  • Subclass it and create a subclass

  • Use the Decorator Pattern and still use the original class

The Decorator class code structure is shown below that extends the base Pizza class.
 

Public class Decorator: Pizza

{

    Pizza basePizza = null;

 

    protected double p_Price = 0.0;

 

    protected Decorator(Pizza objPizza)

    {

        basePizza = objPizza;

    }      

    public override double  GetPrice()

    {

        return p_Price + basePizza.GetPrice();

    }

}


First, this class extends the Pizza abstract class. The reason for that is a ThikCrust with a Component will also be a Pizza and thus all the operations possible on a Pizza should also be possible on a decorated Pizza.

The classes CheezPizzaDecorator and OnionPizzaDecorator extends the Decorator class also and has its own added behavior. You can find this class implementation in the sample application.

Now our client application can create a combination of these ConcreteComponents with any Decorator. Let's look at the sample code implementation for the client.

DecoratorPatt2.jpg

DecoratorPatt2.5.jpg
The following will be the output:

DecoratorPatt3.jpg
It's very easy to understand, especially for those who are not familiar with this pattern. Hope you enjoyed this illustration.

Enjoy Coding.