Do you need to extend the capabilities of your existing class instance at run-time? If the answer is yes then Decorator design pattern just provides the functionality you need.
When we have to change the capabilities of only a particular instance and not all the instances which will get created for a particular class, we have to use decorator design pattern.
This is achieved by creating a decorator class, which wraps the original class. The original class is sub-classed into two parts. One is the concrete class which is essentially the original class with only basic features. The other one is the Decorator base class. This decorator base class implements the same interface as the original class. In addition it wraps the original base class.
We can extend this Decorator base class to create multiple concrete decorator classes. Each of these concrete decorator classes implement their own methods and will call the base class's instance's method.
Now this looks complete babbling. Let's see what I mean actually.
I know the above diagram looks overwhelming. So let's explain it in more simple language with much simpler example.
Lets prepare a subway burger. Shall we ;)
Now we all know that when we visit a Subway store, we have a variety of options to customize our Sub.
Assuming that we have chosen a foot-long already for the base bread, we start making our sandwich.
Depending on our choices, the sandwich is prepared. And we are ready to eat it .. Aren't we :)
Now consider the bread(foot-long) as the Base Component Class. Over this component, we can place a Decorator Base Class SubDecorator and now the Concrete Decorators can be derived from this class.
CheeseDecorator, VegDecorator, SauceDecorator are concrete decorators which implement their own functions and have their own members in addition to the base class functions cost() and description().
And here comes the code:
When we have to change the capabilities of only a particular instance and not all the instances which will get created for a particular class, we have to use decorator design pattern.
This is achieved by creating a decorator class, which wraps the original class. The original class is sub-classed into two parts. One is the concrete class which is essentially the original class with only basic features. The other one is the Decorator base class. This decorator base class implements the same interface as the original class. In addition it wraps the original base class.
We can extend this Decorator base class to create multiple concrete decorator classes. Each of these concrete decorator classes implement their own methods and will call the base class's instance's method.
Now this looks complete babbling. Let's see what I mean actually.
![]() |
| Decorator Design Pattern |
I know the above diagram looks overwhelming. So let's explain it in more simple language with much simpler example.
Lets prepare a subway burger. Shall we ;)
Now we all know that when we visit a Subway store, we have a variety of options to customize our Sub.
Assuming that we have chosen a foot-long already for the base bread, we start making our sandwich.
- We can add cheese to the sandwich.
- We can add vegetables to our Sub.
- We can add mayonnaise,mustard, sweet onion etc .
Depending on our choices, the sandwich is prepared. And we are ready to eat it .. Aren't we :)
Now consider the bread(foot-long) as the Base Component Class. Over this component, we can place a Decorator Base Class SubDecorator and now the Concrete Decorators can be derived from this class.
CheeseDecorator, VegDecorator, SauceDecorator are concrete decorators which implement their own functions and have their own members in addition to the base class functions cost() and description().
And here comes the code:
Decorator Design Pattern Implementation (C++)
#include <iostream>
#include <string>
//Uncomment the next line to enable debug logs
//#define DEBUG
std::string c(const std::string cls) {
return "\n" + cls + " Constructor";
}
std::string d(const std::string cls) {
return "\n" +cls + " Destructor";
}
/*Base component class*/
class Sandwich
{
public:
virtual ~Sandwich() { }
virtual double getCost()=0;
virtual std::string getDesc()=0;
};
/*Concrete component class*/
class WheatBread:public Sandwich
{
public:
WheatBread() {
#ifdef DEBUG
std::cout<<c("WheatBread");
#endif
}
~WheatBread() {
#ifdef DEBUG
std::cout<<d("WheatBread");
#endif
}
std::string getDesc()
{
return "Wheat Bread";
}
double getCost()
{
return 2.0;
}
};
/*Concrete component class*/
class WholeGrainBread:public Sandwich
{
public:
WholeGrainBread() {
#ifdef DEBUG
std::cout<<c("WholeGrainBread");
#endif
}
~WholeGrainBread() {
#ifdef DEBUG
std::cout<<d("WholeGrainBread");
#endif
}
std::string getDesc()
{
return "WholeGrain Bread";
}
double getCost()
{
return 3.0;
}
};
/*Concrete component class*/
class ItalianBread:public Sandwich
{
public:
ItalianBread() {
#ifdef DEBUG
std::cout<<c("ItalianBread");
#endif
}
~ItalianBread() {
#ifdef DEBUG
std::cout<<d("ItalianBread");
#endif
}
std::string getDesc()
{
return "Italian Bread";
}
double getCost()
{
return 2.5;
}
};
/*Decorator Base class*/
class SubDecorator: public Sandwich
{
Sandwich *sandwich;
public:
SubDecorator(Sandwich *sandwichRef)
{
#ifdef DEBUG
std::cout<<c("SubDecorator");
#endif
sandwich = sandwichRef;
}
~SubDecorator() {
#ifdef DEBUG
std::cout<<d("SubDecorator");
#endif
delete sandwich;
}
double getCost()
{
return sandwich->getCost();
}
std::string getDesc()
{
return sandwich->getDesc();
}
};
/*Decorator concrete class*/
class CheeseDecorator:public SubDecorator
{
private:
std::string cheese_desc()
{
return " + Cheese";
}
double cheese_cost;
public:
CheeseDecorator(Sandwich *sandwich):SubDecorator(sandwich)
{
#ifdef DEBUG
std::cout<<c("CheeseDecorator");
#endif
cheese_cost = 3.0;
}
~CheeseDecorator() {
#ifdef DEBUG
std::cout<<d("CheeseDecorator");
#endif
}
std::string getDesc()
{
return SubDecorator::getDesc().append(cheese_desc());
}
double getCost()
{
return SubDecorator::getCost() + cheese_cost;
}
};
/*Decorator concrete class*/
class VegDecorator:public SubDecorator
{
private:
std::string veg_desc()
{
return " + Veg";
}
double veg_cost;
public:
VegDecorator(Sandwich *sandwich):SubDecorator(sandwich)
{
#ifdef DEBUG
std::cout<<c("VegDecorator");
#endif
veg_cost = 2.0;
}
~VegDecorator() {
#ifdef DEBUG
std::cout<<d("VegDecorator");
#endif
}
std::string getDesc()
{
return SubDecorator::getDesc().append(veg_desc());
}
double getCost()
{
return SubDecorator::getCost() + veg_cost;
}
};
/*Decorator concrete class*/
class SauceDecorator:public SubDecorator
{
private:
std::string sauce_desc()
{
return " + Sauce";
}
double sauce_cost;
public:
SauceDecorator(Sandwich *sandwich):SubDecorator(sandwich)
{
#ifdef DEBUG
std::cout<<c("SauceDecorator");
#endif
sauce_cost = .5;
}
~SauceDecorator() {
#ifdef DEBUG
std::cout<<d("SauceDecorator");
#endif
}
std::string getDesc()
{
return SubDecorator::getDesc().append(sauce_desc());
}
double getCost()
{
return SubDecorator::getCost() + sauce_cost;
}
};
int main()
{
Sandwich *sandwich = new CheeseDecorator(new WheatBread());
sandwich = new VegDecorator(sandwich);
sandwich = new SauceDecorator(new SubDecorator(sandwich));
std::cout<<"\nYour sandwich is "<<sandwich->getDesc()<<" and costs $"<<sandwich->getCost();
delete sandwich;
}

























