//
Purpose. Decorator design pattern
//
1. Create a "lowest common denominator" that makes classes
interchangeable
// 2. Create a second level base class for optional
functionality
// 3. "Core" class and "Decorator" class
declare an "isa" relationship
// 4. Decorator class
"hasa" instance of the "lowest common denominator"
//
5. Decorator class delegates to the "hasa" object
// 6. Create a
Decorator derived class for each optional embellishment
// 7. Decorator
derived classes delegate to base class AND add extra stuf
// 8. Client has
the responsibility to compose desired configurations
#include
<iostream>
using namespace std;
class Widget { public:
virtual void draw() = 0; }; // 1.
"lowest common denom"
class TextField : public Widget
{ // 3.
"Core" class & "isa"
int width, height;
public:
TextField( int w, int h ) { width = w; height = h; }
/*virtual*/ void draw() { cout <<
"TextField: " << width << ", " << height
<< '\n'; }
};
// 2. 2nd level base class
class
Decorator : public Widget {
// 3. "isa" relationship
Widget* wid; // 4. "hasa"
relationship
public:
Decorator( Widget* w ) { wid =
w; }
/*virtual*/ void draw() {
wid->draw(); } // 5.
Delegation
};
class BorderDecorator : public Decorator {
public: // 6. Optional
embellishment
BorderDecorator(
Widget* w ) : Decorator( w ) { }
/*virtual*/ void draw() {
Decorator::draw();
// 7. Delegate to
base class
cout <<
" BorderDecorator" <<
'\n'; // and add extra stuff
} };
class ScrollDecorator : public
Decorator { public: // 6. Optional
embellishment
ScrollDecorator(
Widget* w ) : Decorator( w ) { }
/*virtual*/ void draw() {
Decorator::draw(); // 7. Delegate to base class
cout << " ScrollDecorator" << '\n'; //
and add extra stuff
}
};
void main( void ) {
// 8. Client has the responsibility to compose desired
configurations
Widget* aWidget =
new BorderDecorator(
new BorderDecorator(
new
ScrollDecorator(
new TextField( 80, 24 ))));
aWidget->draw();
}
//
TextField: 80, 24
//
ScrollDecorator
//
BorderDecorator
//
BorderDecorator
// Purpose. Inheritance run amok
#include
<iostream>
using namespace std;
class A { public:
virtual void doIt() { cout << 'A';
}
};
class AwithX : public A {
void doX() { cout << 'X'; }
public:
/*virtual*/ void doIt() {
A::doIt();
doX();
} };
class AwithY : public A {
protected:
void doY() { cout << 'Y'; }
public:
/*virtual*/ void doIt() {
A::doIt();
doY();
} };
class AwithZ : public A {
protected:
void doZ() { cout << 'Z'; }
public:
/*virtual*/ void doIt() {
A::doIt();
doZ();
} };
class AwithXY : public AwithX, public AwithY {
public:
/*virtual*/ void doIt()
{
AwithX::doIt();
AwithY::doY();
} };
class AwithXYZ : public
AwithX, public AwithY, public AwithZ { public:
/*virtual*/ void doIt() {
AwithX::doIt();
AwithY::doY();
AwithZ::doZ();
} };
void
main( void ) {
AwithX anX;
AwithXY anXY;
AwithXYZ
anXYZ;
anX.doIt(); cout << '\n';
anXY.doIt(); cout << '\n';
anXYZ.doIt(); cout <<
'\n';
}
// AX
// AXY
// AXYZ
//
Purpose. Replacing inheritance with
wrapping-delegation
//
// Discussion. Use aggregation instead of inheritance to implement
//
embellishments to a "core" object.
Client can dynamically compose
// permutations, instead of the
architect statically wielding multiple
// inheritance.
#include
<iostream>
using namespace std;
class I { public:
virtual ~I() { }
virtual void doIt() = 0;
};
class
A : public I { public:
~A() {
cout << "A dtor" << '\n'; }
/*virtual*/ void doIt() { cout <<
'A'; }
};
class D : public I {
I* wrappee;
public:
D( I* inner ) { wrappee
= inner; }
~D() { delete wrappee; }
/*virtual*/ void doIt() {
wrappee->doIt(); }
};
class X : public D { public:
X( I* core ) : D(core) { }
~X() { cout << "X dtor"
<< " "; }
/*virtual*/ void doIt() { D::doIt(); cout << 'X'; }
};
class
Y : public D { public:
Y( I*
core ) : D(core) { }
~Y() { cout
<< "Y dtor" << "
"; }
/*virtual*/
void doIt() { D::doIt(); cout <<
'Y'; }
};
class Z : public D { public:
Z( I* core ) : D(core) { }
~Z() { cout << "Z dtor"
<< " "; }
/*virtual*/ void doIt() { D::doIt(); cout << 'Z'; }
};
void
main( void ) {
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->doIt(); cout <<
'\n';
anXY->doIt(); cout << '\n';
anXYZ->doIt(); cout << '\n';
delete anX; delete anXY; delete anXYZ;
}
// AX
//
AXY
// AXYZ
// X dtor A
dtor
// Y dtor X dtor A dtor
// Z dtor Y dtor
X dtor A dtor
//
Purpose. Decorator - encoding and
decoding layers of header/packet/trailer
#include <iostream>
#include
<string>
using namespace std;
class Interface {
public:
virtual ~Interface() {
}
virtual void write(
string& ) = 0;
virtual void
read( string& ) = 0;
};
class
Core : public Interface { public:
~Core() { cout << "dtor-Core\n"; }
/*virtual*/ void write( string& b ) { b
+= "MESSAGE|"; }
/*virtual*/ void read( string& );
};
class Decorator
: public Interface {
Interface*
inner;
public:
Decorator(
Interface* c ) { inner = c; }
~Decorator() {
delete inner; }
/*virtual*/ void
write( string& b ) { inner->write( b ); }
/*virtual*/ void read( string& b ) { inner->read( b );
}
};
class Wrapper : public Decorator {
string forward, backward;
public:
Wrapper( Interface* c, string str ) :
Decorator(c) {
forward =
str;
string::reverse_iterator
it;
it = str.rbegin();
for ( ; it != str.rend(); ++it)
backward += *it;
}
~Wrapper() { cout << "dtor-" << forward <<
" "; }
void write( string& );
void read(
string& );
};
void main( void ) {
Interface* object = new Wrapper( new
Wrapper( new Wrapper(
new Core(), "123" ),
"abc" ), "987" );
string buf;
object->write( buf );
cout << "main: " << buf << endl;
object->read( buf );
delete object;
}
// main:
987]abc]123]MESSAGE|321]cba]789]
// Wrapper: 987
// Wrapper:
abc
// Wrapper: 123
// Core: MESSAGE
// Wrapper: 321
//
Wrapper: cba
// Wrapper: 789
// dtor-987 dtor-abc dtor-123 dtor-Core
void
Core::read(string& b) {
int
num = b.find_first_of( '|' );
cout << "Core: " << b.substr(0,num) <<
'\n';
b = b.substr(num+1);
}
void
Wrapper::write( string& b ) {
b += forward + "]";
Decorator::write( b );
b
+= backward + "]";
}
void Wrapper::read( string&
b ) {
int num = b.find_first_of(
']' );
cout <<
"Wrapper: " << b.substr(0,num) << '\n';
b = b.substr(num+1);
Decorator::read( b );
num = b.find_first_of( ']' );
cout << "Wrapper: "
<< b.substr(0,num) << '\n';
b = b.substr(num+1);
}