// Purpose.  Prototype                  #include <iostream.h>
//           creation via delegation
// Discussion.  The architect has done  class Stooge { public:
// an admirable job of decoupling the      virtual Stooge* clone() = 0;
// client from Stooge concrete derived     virtual void slapStick() = 0;
// classes and exercising polymor-      };
// phism.  But there remains coup-
// ling where instances are actually    class Factory {
// created.  If we design an "extra     public:
// level of indirection" (a "factory")     static Stooge* create( int i );
// and have clients use it (instead of  private:
// "new"), then the last bit of coup-      static Stooge* prototypes_[4];
// ling goes away.  The Prototype       };
// pattern suggests delegating the
// creation service to contained ob-    void main( void )
// jects that know how to "clone"       {
// themselves.  This strategy also         Stooge*  roles[10];
// allows us to retire the "case"          int      in, j, i = 0;
// statement in main().
                                           cout << "L(1) M(2) C(3) Go(0): ";
#include <iostream.h>                      cin >> in;
                                           while (in) {
class Stooge { public:                        roles[i++] = Factory::create(in);
   virtual void slapStick() = 0;              cout << "L(1) M(2) C(3) Go(0): ";
};                                            cin >> in; }

class Larry : public Stooge { public:      for (j=0; j < i; j++)
   void slapStick() {                         roles[j]->slapStick();
      cout << "Larry: poke eyes"
         << endl; }                        for (j=0; j < i; j++)
};                                            delete roles[j];
class Moe : public Stooge { public:     }
   void slapStick() {
      cout << "Moe: slap head"          class Larry : public Stooge { public:
         << endl; }                        Stooge* clone() { return new Larry;
};                                         void slapStick() {
class Curly : public Stooge { public:         cout << "Larry: poke eyes"
   void slapStick() {                            << endl; }
      cout << "Curly: suffer abuse"     };
         << endl; }                     class Moe : public Stooge { public:
};                                         Stooge* clone() { return new Moe; }
                                           void slapStick() {
void main( void )                             cout << "Moe: slap head"
{                                                << endl; }
   Stooge*  roles[10];                  };
   int      in, j, i = 0;               class Curly : public Stooge { public:
                                           Stooge* clone() {return new Curly;}
   cout << "L(1) M(2) C(3) Go(0): ";       void slapStick() {
   cin >> in;                                 cout << "Curly: suffer abuse"
   while (in) {                                  << endl; }
      if (in == 1)                      };
         roles[i++] = new Larry;
      else if (in == 2)                 Stooge* Factory::prototypes_[] = { 0,
         roles[i++] = new Moe;             new Larry, new Moe, new Curly };
      else                              Stooge* Factory::create( int i ) {
         roles[i++] = new Curly;           return prototypes_[i]->clone(); }
      cout << "L(1) M(2) C(3) Go(0): ";
      cin >> in; }                      // L(1) M(2) C(3) Go(0): 1
                                        // L(1) M(2) C(3) Go(0): 2
   for (j=0; j < i; j++)                // L(1) M(2) C(3) Go(0): 3
      roles[j]->slapStick();            // 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
      delete roles[j];                  // Moe: slap head
}                                       // Curly: suffer abuse
                                        // Larry: poke eyes



// Purpose.  Prototype design pattern demo
//
// Discussion.  Image base class provides the mechanism for storing,
// finding, and cloning the prototype for all derived classes.  Each
// derived class specifies a private static data member whose
// initialization "registers" a prototype of itself with the base class.
// When the client asks for a "clone" of a certain type, the base class
// finds the prototype and calls clone() on the correct derived class.

#include <iostream.h>

enum imageType { LSAT, SPOT };


class Image {
public:
      virtual void      draw()       = 0;
      static  Image*    findAndClone( imageType );
protected:
      virtual imageType returnType() = 0;
      virtual Image*    clone()      = 0;
      // As each subclass of Image is declared, it registers its prototype
      static void addPrototype( Image* image )
            { _prototypes[_nextSlot++] = image; }
private:
      // addPrototype() saves each registered prototype here
      static Image* _prototypes[10];
      static int    _nextSlot;
};

Image* Image::_prototypes[];
int    Image::_nextSlot;

// Client calls this public static member function when it needs an instance
// of an Image subclass
Image* Image::findAndClone( imageType type )
{
      for (int i=0; i < _nextSlot; i++)
            if (_prototypes[i]->returnType() == type)
                  return _prototypes[i]->clone();
}


class LandSatImage : public Image {
public:
      imageType returnType() { return LSAT; }
      void      draw()       { cout << "LandSatImage::draw " << _id << endl; }
      // When clone() is called, call the one-argument ctor with a dummy arg
      Image*    clone()      { return new LandSatImage( 1 ); }
protected:
      // This is only called from clone()
      LandSatImage( int dummy ) { _id = _count++; }
private:
      // Mechanism for initializing an Image subclass - this causes the
      // default ctor to be called, which registers the subclass's prototype
      static LandSatImage _landSatImage;
      // This is only called when the private static data member is inited
      LandSatImage() { addPrototype( this ); }
      // Nominal "state" per instance mechanism
      int        _id;
      static int _count;
};

// Register the subclass's prototype
LandSatImage LandSatImage::_landSatImage;
// Initialize the "state" per instance mechanism
int          LandSatImage::_count = 1;


class SpotImage : public Image {
public:
      imageType returnType() { return SPOT; }
      void      draw()       { cout << "SpotImage::draw " << _id << endl; }
      Image*    clone()      { return new SpotImage( 1 ); }
protected:
      SpotImage( int dummy ) { _id = _count++; }
private:
      SpotImage() { addPrototype( this ); }
      static SpotImage _spotImage;
      int        _id;
      static int _count;
};

SpotImage SpotImage::_spotImage;
int       SpotImage::_count = 1;


// Simulated stream of creation requests
const int  NUM_IMAGES = 8;
imageType  input[NUM_IMAGES] =
      { LSAT, LSAT, LSAT, SPOT, LSAT, SPOT, SPOT, LSAT };

void main() {
      Image*  images[NUM_IMAGES];

      // Given an image type, find the right prototype, and return a clone
      for (int i=0; i < NUM_IMAGES; i++)
            images[i] = Image::findAndClone( input[i] );

      // Demonstrate that correct image objects have been cloned
      for (i=0; i < NUM_IMAGES; i++)
            images[i]->draw();

      // Free the dynamic memory
      for (i=0; i < NUM_IMAGES; i++)
            delete images[i];
}

// LandSatImage::draw 1
// LandSatImage::draw 2
// LandSatImage::draw 3
// SpotImage::draw 1
// LandSatImage::draw 4
// SpotImage::draw 2
// SpotImage::draw 3
// LandSatImage::draw 5