- Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
- Decorator pattern helps to add more responsibilities to objects at runtime unlike inheritance, in which the behavior is fixed at compile time.
- Decorator is required when there can be a variety of optional operations that can precede or follow another function that is always executed.
- Decorator is also known as wrapper.
#include <iostream>
#include <string>
using namespace std;
class CGreeting {
public:
virtual ~CGreeting() {
}
virtual string m_getGreeting() const=0;
};
class CExclamation : public CGreeting {
private:
const CGreeting & greeting;
public:
CExclamation(const CGreeting & gr) : greeting(gr) { }
string m_getGreeting() const {
return greeting.m_getGreeting() + "!";
}
};
class CHelloWorld : public CGreeting {
public:
string m_getGreeting() const {
return "Hello world";
}
};
void helloworld(const CGreeting & greeting) {
cout << greeting.m_getGreeting() << endl;
}
int main() {
CHelloWorld hw;
helloworld(CExclamation(hw));
return 0;
}
- While creating a decorator, its interface should be similar to the object it decorates, therefore should inherit from the same class as that of the object.
- The base class of the component and the decorator should be light weight and should not store any data. Otherwise it will make the decorators too heavy to use.
Advantages:
- Responsibilities can be added to an object dynamically rather than static inheritance where responsibility is fixed at compile time.
- Responsibilities can be detached at runtime.
- Instead of putting all features in one base class, you add the features as the code progresses.
- You pay for the features only if you use them.
- It is easy to add any combination of capabilities. The same capability can even be added twice.
Disadvantages:
- Lots of small objects are created which makes the system harder to understand and debug.
When to use this pattern:
Use the decorator pattern when
- You want to add responsibilities to individual objects dynamically and transparently without affecting other objects.
- Responsibilities have to be withdrawn.