Decorator
Description:
Add responsibilities to objects dynamically
Intent
- Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
- Client-specified embellishment of a core object by recursively wrapping it.
- Wrapping a gift, putting it in a box, and wrapping the box.
Example:
Note
Idea:
Check list
- Ensure the context is: a single core (or non-optional) component, several optional embellishments or wrappers, and an interface that is common to all.
- Create a "Lowest Common Denominator" interface that makes all classes interchangeable.
- Create a second level base class (Decorator) to support the optional wrapper classes.
- The Core class and Decorator class inherit from the LCD interface.
- The Decorator class declares a composition relationship to the LCD interface, and this data member is initialized in its constructor.
- The Decorator class delegates to the LCD object.
- Define a Decorator derived class for each optional embellishment.
- Decorator derived classes implement their wrapper functionality - and - delegate to the Decorator base class.
- The client configures the type and ordering of Core and Decorator objects.
Code:
class I {
public:
virtual ~I(){}
virtual void do_it() = 0;
};
class A: public I {
public:
~A() {
cout << "A dtor" << '\n';
}
/*virtual*/
void do_it() {
cout << 'A';
}
};
class D: public I {
public:
D(I *inner) {
m_wrappee = inner;
}
~D() {
delete m_wrappee;
}
/*virtual*/
void do_it() {
m_wrappee->do_it();
}
private:
I *m_wrappee;
};
class X: public D {
public:
X(I *core): D(core){}
~X() {
cout << "X dtor" << " ";
}
/*virtual*/
void do_it() {
D::do_it();
cout << 'X';
}
};
class Y: public D {
public:
Y(I *core): D(core){}
~Y() {
cout << "Y dtor" << " ";
}
/*virtual*/
void do_it() {
D::do_it();
cout << 'Y';
}
};
class Z: public D {
public:
Z(I *core): D(core){}
~Z() {
cout << "Z dtor" << " ";
}
/*virtual*/
void do_it() {
D::do_it();
cout << 'Z';
}
};
int main() {
I *anX = new X(new A);
I *anXY = new Y(new X(new A));
I *anXYZ = new Z(new Y(new X(new A)));
anX->do_it();
cout << '\n';
anXY->do_it();
cout << '\n';
anXYZ->do_it();
cout << '\n';
delete anX;
delete anXY;
delete anXYZ;
}
Output
AX
AXY
AXYZ
X dtor A dtor
Y dtor X dtor A dtor
Z dtor Y dtor X dtor A dtor