// Purpose.  Factory Method             #include <iostream>
//           creation via inheritance   using namespace std;
//
// Discussion.  The architect has done  class Stooge {
// an admirable job of decoupling the   public:
// client from Stooge concrete derived     virtual void slapStick() = 0;
// classes, and, exercising polymor-    };
// phism.  But there remains coupling
// where instances are actually         class Factory {
// created.  If we design an "extra     public:
// level of indirection" (a "factory       // Factory Method (virtual ctor)
// method") and have clients use it        static Stooge* create( int );
// (instead of "new"), then the last    };
// bit of coupling goes away.  The
// "factory method" (aka "virtual       void main( void ) {
// constructor") can be defined in the     Stooge*  roles[10];
// Stooge base class, or, in a             int      in, j, i = 0;
// separate "factory" class.  Note
// that main() is no longer dependent      while (1) {
// on Stooge derived classes.                 cout << "L(1) M(2) C(3) Go(0): ";
                                              cin >> in;
#include <iostream>                           if ( ! in ) break;
using namespace std;                          roles[i++] = Factory::create(in);
                                           }
class Stooge { public:                     for (j=0; j < i; j++)
   virtual void slapStick() = 0;              roles[j]->slapStick();
};                                         for (j=0; j < i; j++)
                                              delete roles[j];
class Larry : public Stooge { public:   }
   void slapStick() {
      cout << "Larry: poke eyes"        class Larry : public Stooge { public:
         << endl; }                        void slapStick() {
};                                            cout << "Larry: poke eyes"
class Moe : public Stooge { public:              << endl; }
   void slapStick() {                   };
      cout << "Moe: slap head"          class Moe : public Stooge { public:
         << endl; }                        void slapStick() {
};                                            cout << "Moe: slap head"
class Curly : public Stooge { public:            << endl; }
   void slapStick() {                   };
      cout << "Curly: suffer abuse"     class Curly : public Stooge { public:
         << endl; }                        void slapStick() {
};                                            cout << "Curly: suffer abuse"
                                                 << endl; }
void main( void ) {                     };
   Stooge*  roles[10];
   int      in, j, i = 0;               Stooge* Factory::create( int in ) {
                                           if (in == 1)
   cout << "L(1) M(2) C(3) Go(0): ";          return new Larry;
   cin >> in;                              else if (in == 2)
   while (in) {                               return new Moe;
      if (in == 1)                         else
         roles[i++] = new Larry;              return new Curly;
      else if (in == 2)                 }
         roles[i++] = new Moe;
      else                              // L(1) M(2) C(3) Go(0): 1
         roles[i++] = new Curly;        // L(1) M(2) C(3) Go(0): 2
      cout << "L(1) M(2) C(3) Go(0): "; // L(1) M(2) C(3) Go(0): 3
      cin >> in;                        // L(1) M(2) C(3) Go(0): 1
   }                                    // L(1) M(2) C(3) Go(0): 0
   for (j=0; j < i; j++)                // Larry: poke eyes
      roles[j]->slapStick();            // Moe: slap head
   for (j=0; j < i; j++)                // Curly: suffer abuse
      delete roles[j];                  // Larry: poke eyes
}



// Purpose.  Factory Method design pattern demo.
//
// Discussion.  Frameworks are applications (or subsystems) with "holes"
// in them.  Each framework specifies the infrastructure, superstructure,
// and flow of control for its "domain", and the client of the framework
// may: exercise the framework's default behavior "as is", extend selected
// pieces of the framework, or replace selected pieces.  The Factory
// Method pattern addresses the notion of "creation" in the context of
// frameworks.  In this example, the framework knows WHEN a new document
// should be created, not WHAT kind of Document to create.  The
// "placeholder" Application::CreateDocument() has been declared by the
// framework, and the client is expected to "fill in the blank" for
// his/her specific document(s).  Then, when the client asks for
// Application::NewDocument(), the framework will subsequently call the
// client's MyApplication::CreateDocument().

#include <iostream.h>

/* Abstract base class declared by framework */
class Document {
public:
      Document( char* fn ) { strcpy( name, fn ); }
      virtual void Open()  = 0;
      virtual void Close() = 0;
      char* GetName()      { return name; }
private:
      char  name[20];
};

/* Concrete derived class defined by client */
class MyDocument : public Document {
public:
      MyDocument( char* fn ) : Document(fn) { }
      void Open()   { cout << "   MyDocument: Open()" << endl; }
      void Close()  { cout << "   MyDocument: Close()" << endl; }
};


/* Framework declaration */
class Application {
public:
      Application() : _index(0) { cout << "Application: ctor" << endl; }
      /* The client will call this "entry point" of the framework */
      NewDocument( char* name )  {
            cout << "Application: NewDocument()" << endl;
            /* Framework calls the "hole" reserved for client customization */
            _docs[_index] = CreateDocument( name );
            _docs[_index++]->Open(); }
      OpenDocument()  { }
      void ReportDocs();
      /* Framework declares a "hole" for the client to customize */
      virtual Document* CreateDocument( char* ) = 0;
private:
      int        _index;
      /* Framework uses Document's base class */
      Document*  _docs[10];
};

void Application::ReportDocs() {
      cout << "Application: ReportDocs()" << endl;
      for (int i=0; i < _index; i++)
            cout << "   " << _docs[i]->GetName() << endl; }


/* Customization of framework defined by client */
class MyApplication : public Application {
public:
      MyApplication() { cout << "MyApplication: ctor" << endl; }
      /* Client defines Framework's "hole" */
      Document* CreateDocument( char* fn ) {
            cout << "   MyApplication: CreateDocument()" << endl;
            return new MyDocument( fn ); }
};

void main() {
      /* Client's customization of the Framework */
      MyApplication  myApp;

      myApp.NewDocument( "foo" );
      myApp.NewDocument( "bar" );
      myApp.ReportDocs();
}

// Application: ctor
// MyApplication: ctor
// Application: NewDocument()
//    MyApplication: CreateDocument()
//    MyDocument: Open()
// Application: NewDocument()
//    MyApplication: CreateDocument()
//    MyDocument: Open()
// Application: ReportDocs()
//    foo
//    bar