//
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