Back to: Design Patterns in C# With Real-Time Examples
Decorator Design Pattern Real-Time Example in C# – Pizza
In this article, I am going to discuss the Decorator Design Pattern Real-Time Example in C# – Pizza. Please read our previous article where we discussed the basic concepts of the Decorator Design Pattern in C# with Examples.
As we already discussed in our Previous Article, the Decorator Design Pattern is used to add new functionalities to an existing object at run time without modifying the structure of the existing objects. This is the reason why it belongs to the structural design pattern category. With this kept in mind let us try to understand the real-time example of Pizza using the Decorator Design Pattern in C#.
Decorator Design Pattern Real-Time Example in C# – Pizza
Suppose you want to prepare either chicken pizza or vegetable pizza. Then what you need to do is, first you need to prepare the plain pizza. Then the Pizza Decorator will add chicken to the plain pizza if you want chicken pizza or it will add vegetables to the plain pizza if you want vegetable pizza. So, you are getting chicken pizza or vegetable pizza by adding chicken or vegetables to the plain pizza by the Pizza decorator.
So, as per the Decorator Design Pattern, it will add additional functionalities or behaviors to an existing object. So, in this case, Plain pizza is the existing object, and adding chicken or vegetable (based on the type of pizza you want) by the pizza decorator is the additional functionality.
So, if you want vegetable pizza, then the pizza decorator will add vegetables to the plain pizza and return the veg pizza. In the same way, if you want chicken pizza, then the pizza decorator will add chicken to the plain pizza and return the chicken pizza. This is one of the best examples of the Decorator Design Pattern.
Class Diagram of Pizza Example using Decorator Design Pattern:
Please have a look at the following image.
At the top, you can see the Pizza interface and it has the MakePizza method. This interface is implemented by the PlainPizza concrete class and provides the implementation for the MakePizza method. So, when we call the MakePizza method on the PlainPizza object it will return plain pizza to the caller.
The PizzaDecorator is an abstract class and it also implements the Pizza interface. It has Constructor and to the constructor, we need to pass the pizza object which we want to decorate.
The PizzaDecorator abstract class is extended to two concrete classes i.e. ChickenPizzaDecorator and VegPizzaDecorator. Both this class overrides the MakePizza method. The ChickenPizzaDecorator will add chicken to the Plain Pizza and return the chicken pizza to the caller. Similarly, the VegPizzaDecorator will add vegetables to the Plain Pizza and return Veg Pizza to the caller.
On the left-hand side, you can see the client and it has the main method. This method is used to extend the functionality of pizza objects by using the decorator design pattern.
Implementation of Pizza using Decorator Design pattern in C#:
Let us implement the above Real-Time Example Pizza using the Decorator Design Pattern step by step using C# Language.
Step1: Creating the Pizza interface (Component)
This is going to be an interface. So, create an interface with the name Pizza.cs and then copy and paste the following code into it. This Pizza interface has one abstract method i.e. MakePizza. The following interface defines operators which can be altered by the decorators.
namespace DecoratorDesignPatternRealTimeExample { // This is the Base Component interface that defines operations that can be altered by decorators public interface Pizza { string MakePizza(); } }
Step2: Creating Plain Pizza (Concrete Component)
This is going to be a concrete class. So, create a class file with the name PlainPizza.cs and then copy and paste the following code into it. This class implements the Pizza interface and provides the default implementation for the MakePizza method. What this MakePizza method will do is, it will simply return a Plain Pizza to the caller. Later as per the requirement of the client, we will add either a Chicken or Vegetables to this pizza.
namespace DecoratorDesignPatternRealTimeExample { // Concrete Components provide default implementations of the operations. public class PlainPizza : Pizza { //The following MakePizza method returns the default Pizza public string MakePizza() { return "Plain Pizza"; } } }
Step3: Creating Pizza Decorator (Decorator)
This is going to be an abstract class. So, create a class with the name PizzaDecorator.cs and then copy and paste the following code into it. This class also implements the Pizza interface and provides the implementation for the MakePizza method. The existing pizza object which we want to decorate needs to be passed as an argument to the constructor of this class. That existing pizza object which this class received through the constructor is going to be stored in the field that we created here i.e. protected Pizza pizza; We declare the MakePizza method as virtual and the reason for this is, it is going to be overridden by the child concrete decorator classes. The following code is self-explained, so please go through the comment lines.
namespace DecoratorDesignPatternRealTimeExample { //Inherited from the Base Component Interface public abstract class PizzaDecorator : Pizza { //Create a Field to store the existing Pizza Object protected Pizza pizza; //Initializing the Field using Constructor //While Creating an instance of the PizzaDecorator (Instance of the Child Class that Implements PizzaDecorator abstract class) //We need to pass the existing pizza object which we want to decorate public PizzaDecorator(Pizza pizza) { //Store that existing pizza object in the pizza variable this.pizza = pizza; } //Providing Implementation for Pizza Interface i.e. MakePizza Method //Here, we are just calling the Concrete Component ManufactureCar Method using the existing pizza object //We are making this Method Virtual to allow the Child Concrete Decorator classes to override public virtual string MakePizza() { return pizza.MakePizza(); } } }
Step4: Creating Chicken Pizza Decorator (ConcreteDecoratorA )
This is going to be a concrete class. So, create a class file with the name ChickenPizzaDecorator.cs and then copy and paste the following code into it. This class is inherited from the PizzaDecorator abstract class and overrides the MakePizza method. What this MakePizza method will do is, it will add chicken to the plain pizza and will return the Chicken Pizza to the caller. But within the MakePizza method, first, call the MakePizza method on the existing pizza object to create the pizza, and then add the Chicken to the pizza by calling the AddChicken method.
namespace DecoratorDesignPatternRealTimeExample { //The following Concrete Decorator class will add Chicken to Existing Pizza public class ChickenPizzaDecorator : PizzaDecorator { //Pass the existing pizza while creating the Instance of ChickenPizzaDecorator //Also pass the same existing pizza object to the base constructor public ChickenPizzaDecorator(Pizza pizza) : base(pizza) { } //Overriding the MakePizza method to Chicken public override string MakePizza() { //First Call the Concrete Components MakePizza Method and then the AddChicken method return pizza.MakePizza() + AddChicken(); } private string AddChicken() { return ", Chicken added"; } } }
Step5: Creating Veg Pizza Decorator (ConcreteDecoratorB)
This is also going to be a concrete class. So, create a class file with the name VegPizzaDecorator.cs and then copy and paste the following code into it. This class is also inherited from the PizzaDecorator abstract class and also overrides the MakePizza method. The MakePizza method will add the Vegetables to the plain pizza and will return Veg Pizza to the caller. But within the MakePizza method, first, call the MakePizza method on the existing pizza object to create the pizza, and then add the Add Vegetables to the pizza by calling the AddVegetables method.
namespace DecoratorDesignPatternRealTimeExample { //The following Concrete Decorator class will add Vegetables to the Existing Pizza public class VegPizzaDecorator : PizzaDecorator { //Pass the existing pizza object while creating the Instance of VegPizzaDecorator class //Also pass the same existing pizza object to the base class constructor public VegPizzaDecorator(Pizza pizza) : base(pizza) { } //Overriding the MakePizza method to Vegetables public override string MakePizza() { //First Call the Concrete Components MakePizza Method and then the AddVegetables method return pizza.MakePizza() + AddVegetables(); } private string AddVegetables() { return ", Vegetables added"; } } }
Step6: Client
Please modify the Main method as shown below. Here, first, we create an object of PlainPizza and then call the MakePizza method which will create and return plain pizza. Then we create the instance of ChickenPizzaDecorator and pass the Plain Pizza instance as a parameter to the constructor. And when we call the MakePizza method of the ChickenPizzaDecorator instance, it will add Chicken to the plain pizza and return the chicken pizza. The same is in the case of VegPizzaDecorator. The following code is self-explained, so please go through the comment lines for a better understanding.
using System; namespace DecoratorDesignPatternRealTimeExample { class Program { static void Main(string[] args) { //Create an instance of Concrete Component PlainPizza plainPizzaObj = new PlainPizza(); //Calling the MakePizza method will create the pizza without chicken and vegetables string plainPizza = plainPizzaObj.MakePizza(); Console.WriteLine(plainPizza); //Adding Chicken to the Plain Pizza //Create an instance PizzaDecorator class and //pass existing plainPizzaObj as a parameter to the Constructor which we want to decorate PizzaDecorator chickenPizzaDecorator = new ChickenPizzaDecorator(plainPizzaObj); //Calling the MakePizza Method using the chickenPizzaDecorator object will add Chicken to the existing Plain Pizza string chickenPizza = chickenPizzaDecorator.MakePizza(); Console.WriteLine("\n'" + chickenPizza + "' using ChickenPizzaDecorator"); //The Process is the same for adding vegetables to the existing pizza VegPizzaDecorator vegPizzaDecorator = new VegPizzaDecorator(plainPizzaObj); string vegPizza = vegPizzaDecorator.MakePizza(); Console.WriteLine("\n'" + vegPizza + "' using VegPizzaDecorator"); Console.Read(); } } }
Output:
In the next article, I am going to discuss the Bridge Design Pattern in C# with Examples. Here, in this article, I try to explain Real-Time Examples of Decorator Design Patterns using C#. I hope you enjoy this Real-Time Example of Decorator Design Patterns using the C# Language article.
can this be replaced with Fluent? or am i mistaken something?
With FluentPattern, you can write a code in such a way that
Pizza.MakePizza().AddVegetable()
very good
void Main()
{
//Create an instance of Concrete Component
–>> Pizza plainPizzaObj = new PlainPizza();
//Calling the MakePizza method will create the pizza without chicken and vegetables
string plainPizza = plainPizzaObj.MakePizza();
Console.WriteLine(plainPizza);
//Adding Chicken to the Plain Pizza
//Create an instance PizzaDecorator class and
//pass existing plainPizzaObj as a parameter to the Constructor which we want to decorate
–>> Pizza chickenPizzaDecorator = new ChickenPizzaDecorator(plainPizzaObj);
//Calling the MakePizza Method using the chickenPizzaDecorator object will add Chicken to the existing Plain Pizza
string chickenPizza = chickenPizzaDecorator.MakePizza();
Console.WriteLine(“\n'” + chickenPizza + “‘ using ChickenPizzaDecorator”);
//The Process is the same for adding vegetables to the existing pizza
–>> Pizza vegPizzaDecorator = new VegPizzaDecorator(plainPizzaObj);
string vegPizza = vegPizzaDecorator.MakePizza();
Console.WriteLine(“\n'” + vegPizza + “‘ using VegPizzaDecorator”);
Console.Read();
}
Could you give a working version of the decorator example, an example from life.