// Purpose.  Abstract Factory           #include <iostream.h>
//
// Discussion.  Trying to maintain      class Widget { public:
// portability across multiple "plat-      virtual void draw() = 0;
// forms" routinely requires lots of    };
// preprocessor "case" stmts.  The
// Factory pattern suggests defining    class MotifBtn : public Widget {
// a creation services interface in a   public:
// Factory base class, and implement-      void draw() { cout << "MotifBtn"
// ing each "platform" in a separate          << endl; }
// Factory derived class.               };

#include <iostream.h>                   class WindowsBtn : public Widget {
                                        public:
class Widget { public:                     void draw() { cout << "WindowsBtn"
   virtual void draw() = 0;                   << endl; }
};                                      };

class MotifBtn : public Widget {        class Factory { public:
public:                                    virtual Widget* createBtn() = 0;
   void draw() { cout << "MotifBtn"     };
      << endl; }
};                                      class MotifFactory : public Factory {
                                        public:
class WindowsBtn : public Widget {         Widget* createBtn() {
public:                                       return new MotifBtn; }
   void draw() { cout << "WindowsBtn"   };
      << endl; }
};                                      class WindowsFactory : public Factory {
                                        public:
void doThisWindow() {                      Widget* createBtn() {
   // create window, attach btn               return new WindowsBtn; }
#ifdef MOTIF                            };
   Widget* w = new MotifBtn;
#else // WINDOWS                        Factory* factory;
   Widget* w = new WindowsBtn;
#endif                                  void doThisWindow() {
   w->draw(); }                            // create window, attach btn
                                           Widget* w = factory->createBtn();
void doThatWindow() {                      w->draw(); }
   // create window, attach btn
#ifdef MOTIF                            void doThatWindow() {
   Widget* w = new MotifBtn;               // create window, attach btn
#else // WINDOWS                           Widget* w = factory->createBtn();
   Widget* w = new WindowsBtn;             w->draw(); }
#endif
   w->draw(); }                         void main( void )
                                        {
void main( void )                       #ifdef MOTIF
{                                          factory = new MotifFactory;
   // create window, attach btn         #else // WINDOWS
#ifdef MOTIF                               factory = new WindowsFactory;
   Widget* w = new MotifBtn;            #endif
#else // WINDOWS
   Widget* w = new WindowsBtn;             // create window, attach btn
#endif                                     Widget* w = factory->createBtn();
   w->draw();                              w->draw();

   doThisWindow();                         doThisWindow();
   doThatWindow();                         doThatWindow();
}                                       }

// WindowsBtn                           // MotifBtn
// WindowsBtn                           // MotifBtn
// WindowsBtn                           // MotifBtn



// Purpose.  Abstract Factory design pattern demo.
//
// Discussion.  "Think of constructors as factories that churn out objects".
// Here we are allocating the constructor responsibility to a factory object,
// and then using inheritance and virtual member functions to provide a
// "virtual constructor" capability.  So there are two dimensions of
// decoupling occurring.  The client uses the factory object instead of "new"
// to request instances; and, the client "hard-wires" the family, or class, of
// that factory only once, and throughout the remainder of the application
// only relies on the abstract base class.

#include <iostream.h>

class Shape {
public:
   Shape()              { id_ = total_++; }
   virtual void draw()  = 0;
protected:
   int         id_;
   static int  total_;
};
int Shape::total_ = 0;

class Circle : public Shape { public:
   void draw() { cout << "circle " << id_ << ": draw" << endl; } };
class Square : public Shape { public:
   void draw() { cout << "square " << id_ << ": draw" << endl; } };
class Ellipse : public Shape { public:
   void draw() { cout << "ellipse " << id_ << ": draw" << endl; } };
class Rectangle : public Shape { public:
   void draw() { cout << "rectangle " << id_ << ": draw" << endl; } };

class Factory { public:
   virtual Shape* createCurvedInstance()   = 0;
   virtual Shape* createStraightInstance() = 0;
};
class SimpleShapeFactory : public Factory { public:
   Shape* createCurvedInstance()   { return new Circle; }
   Shape* createStraightInstance() { return new Square; }
};
class RobustShapeFactory : public Factory { public:
   Shape* createCurvedInstance()   { return new Ellipse; }
   Shape* createStraightInstance() { return new Rectangle; }
};

void main() {
#ifdef SIMPLE
   Factory*  factory = new SimpleShapeFactory;
#elif ROBUST
   Factory*  factory = new RobustShapeFactory;
#endif
   Shape*    shapes[3];

   shapes[0] = factory->createCurvedInstance();   // shapes[0] = new Ellipse;
   shapes[1] = factory->createStraightInstance(); // shapes[1] = new Rectangle;
   shapes[2] = factory->createCurvedInstance();   // shapes[2] = new Ellipse;

   for (int i=0; i < 3; i++)
      shapes[i]->draw();
}

// ellipse 0: draw
// rectangle 1: draw
// ellipse 2: draw