// 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);
}