Decorator Pattern

The Decorator Pattern provides a flexible alternative to sub classing for extending functionality dynamically.
The idea of the Decorator Pattern is to wrap an existing class, add other functionality to it, then expose the same interface to the outside world. Because of this our decorator exactly looks like the original class to the people who are using it.
It is used to extend or alter the functionality at runtime. It does this by wrapping them in an object of the decorator class without modifying the original object. So it can be called a wrapper pattern.
Advantages of Decorator Pattern
- Adds functionality to existing objects dynamically
- Alternative to sub classing
- Flexible design
- Supports Open Closed Principle
When to use Decorator Pattern
- Legacy System
- Contorls
- Sealed Classes
The following class diagram shows us the Decorator Pattern's design:

- Component: It defines the interface of the actual object that needs functionality to be added dynamically to the ConcreteComponents.
- ConcreteComponent: The actual object in which the functionalities could be added dynamically.
- Decorator: This defines the interface for all the dynamic functionalities that can be added to the ConcreteComponent.
- ConcreteDecorator: All the functionalities that can be added to the ConcreteComponent. Each needed functionality will be one ConcreteDecorator class.
A decorated class is a base class of concrete decorator classes and it inherits from the base component class. So the decorators can be used in the place of concrete components.
Let's start learning the Decorator Pattern with one real time problem. Suppose we need to build an application for a car show room that sells cars along with car accessories. Economy, Deluxe and Luxury are the car categories that come with the optional accessories packages Basic, Advanced and Sport. So the application must provide the car cost adding the cost of accessory package if the user chooses any of the preceding packages.
Okay. Let's start designing our application with the ICar interface that will be implemented by Economy, Deluxe and Luxury Car category classes.
- /// <summary>
- /// Car Base component
- /// </summary>
- public interface ICar
- {
- string GetDescription();
- double GetCost();
- }
- /// <summary>
- /// Concrete Car
- /// </summary>
- public class EconomyCar : ICar
- {
- public string GetDescription()
- {
- return "Economy Car";
- }
- public double GetCost()
- {
- return 450000.0;
- }
- }
- /// <summary>
- /// Concrete Car
- /// </summary>
- public class DeluxCar : ICar
- {
- public string GetDescription()
- {
- return "Delux Car";
- }
- public double GetCost()
- {
- return 750000.0;
- }
- }
- /// <summary>
- /// Concrete Car
- /// </summary>
- public class LuxuryCar : ICar
- {
- public string GetDescription()
- {
- return "Luxury Car";
- }
- public double GetCost()
- {
- return 1000000.0;
- }
- }
- public class EconomyCarWithBasicAccessories: ICar{
- ..
- ..
- }
- public class DeluxCarWithBasicAccessories: ICar{
- ..
- ..
- }
- public class LuxuryCarWithBasicAccessories: ICar{
- ..
- ..
- }
- ..
- ..
- ..
- ..
- public class EconomyCarWithSportAccessories: ICar{
- ..
- ..
- }
- public class DeluxCarWitSportAccessories: ICar{
- ..
- ..
- }
- public class LuxuryCarWithSportAccessories: ICar{
- ..
- ..
- }
To avoid this we can get help from our hero the Decorator Pattern. As I already said, this pattern is used to attach or add extra functionality to the object at run time without altering the class structure. That means there is no need to create extra sub classes whenever we introduce a new car category or new accessory packages.
Let's build our system using the Decorator Pattern.
- /// <summary>
- /// Car Base component
- /// </summary>
- public interface ICar
- {
- string GetDescription();
- double GetCost();
- }
- /// <summary>
- /// Concrete Car
- /// </summary>
- public class EconomyCar : ICar
- {
- public string GetDescription()
- {
- return "Economy Car";
- }
- public double GetCost()
- {
- return 450000.0;
- }
- }
- /// <summary>
- /// Concrete Car
- /// </summary>
- public class DeluxCar : ICar
- {
- public string GetDescription()
- {
- return "Delux Car";
- }
- public double GetCost()
- {
- return 750000.0;
- }
- }
- /// <summary>
- /// Concrete Car
- /// </summary>
- public class LuxuryCar : ICar
- {
- public string GetDescription()
- {
- return "Luxury Car";
- }
- public double GetCost()
- {
- return 1000000.0;
- }
- }
- /// <summary>
- /// Abstract Decorator
- /// </summary>
- public abstract class CarAccessoriesDecorator : ICar
- {
- private ICar _car;
- public CarAccessoriesDecorator(ICar aCar)
- {
- this._car = aCar;
- }
- public virtual string GetDescription()
- {
- return this._car.GetDescription();
- }
- public virtual double GetCost()
- {
- return this._car.GetCost();
- }
- }
- /// <summary>
- /// Concrete Decorator
- /// </summary>
- public class BasicAccessories : CarAccessoriesDecorator
- {
- public BasicAccessories(ICar aCar)
- : base(aCar)
- {
- }
- public override string GetDescription()
- {
- return base.GetDescription() + ",Basic Accessories Package";
- }
- public override double GetCost()
- {
- return base.GetCost() + 2000.0;
- }
- }
- /// <summary>
- /// Concrete Decorator
- /// </summary>
- public class AdvancedAccessories : CarAccessoriesDecorator
- {
- public AdvancedAccessories(ICar aCar)
- : base(aCar)
- {
- }
- public override string GetDescription()
- {
- return base.GetDescription() + ",Advanced Accessories Package";
- }
- public override double GetCost()
- {
- return base.GetCost() + 10000.0;
- }
- }
- /// <summary>
- /// Concrete Decorator
- /// </summary>
- public class SportsAccessories : CarAccessoriesDecorator
- {
- public SportsAccessories(ICar aCar)
- : base(aCar)
- {
- }
- public override string GetDescription()
- {
- return base.GetDescription() + ",Sports Accessories Package";
- }
- public override double GetCost()
- {
- return base.GetCost() + 15000.0;
- }
- }

Here we successfully avoided the sub classing issue. Whenever we need to add a new car category we only must add one class for it like the following.
- public class SuperLuxury : ICar
- {
- public string GetDescription()
- {
- return "Super Luxury Car";
- }
- public double GetCost()
- {
- return 1500000;
- }
- }
- pubic classs ExtremeSportAccessories : CarAccessoryDecorator
- {
- public ExtremeSportAccessories(ICar aCar)
- :base(aCar)
- {
- }
- public override string GetDescription()
- {
- return base.GetDescription() +",Extreme Sport Accessories";
- }
- public override double GetCost()
- {
- return base.GetCost() + 25000;
- }
- }
- static void Main(string[] args)
- {
- //Create EcomomyCar instance.
- ICar objCar = new EconomyCar();
- //Wrp EconomyCar instancw with BasicAccessories.
- CarAccessoriesDecorator objAccessoriesDecorator = new BasicAccessories(objCar);
- //Wrap EconomyCar instance with AdvancedAccessories instance.
- objAccessoriesDecorator = new AdvancedAccessories(objAccessoriesDecorator);
- Console.Write("Car Detials: " + objAccessoriesDecorator.GetDescription());
- Console.WriteLine("\n\n");
- Console.Write("Total Price: " + objAccessoriesDecorator.GetCost());
- Console.Read();
- }
I hope you enjoyed this article. Thank you.

Alex FreitasPosted Jun 2, 2021, 2:10 PM
The class ExtremeSportsAcessories has some typos.
Ankush PatilPosted May 26, 2020, 2:30 AM
Simple and easy explanation. Thanks for sharing :)
VothuongPosted Apr 26, 2020, 1:06 PM
Very nice explanation, thank you!
Deepak BishtPosted Mar 6, 2019, 4:03 AM
Well that is a nice example of decorator pattern. But I am wondering we can implement ICar interface directly to BasicAccessories, AdvanceAccessories and to SportesAccessories without having decorator what purpose exactly Decorator class CarAccessoriesDecorator is serving here?
Aankur SinglaPosted Aug 29, 2018, 2:11 AM
Very nice explanation, thanks a lot for sharing good info
Dennis ThomasPosted Feb 21, 2018, 4:21 AM
Good one Damodhar! Well explained. But I too have the same question which Arun Cm asked.
Arun CmPosted Dec 8, 2017, 1:01 AM
In your article you mentioned "When to use Decorator Pattern" 3rd one is "Sealed Classes" what you meant by that ?
Ramakrishna BasagallaPosted Apr 26, 2016, 1:09 AM
Nice one
Rupali ShindePosted Nov 17, 2015, 1:10 AM
nice, really great article sir
Ch.Smrutiranjan ParidaPosted Nov 11, 2014, 5:59 AM
Good article.(Y)
Vithal WadjePosted Oct 30, 2014, 12:47 PM
super one,one of the great article i have seen ever