// Purpose.  Prototype design pattern lab
//
// Problem.  See the problem statement for the Factory Method lab.  Beyond
// the issues discussed there, we would also like to eliminate the "case"
// statement that currently exists in main().  We can do that by replacing
// the conditional code with a "table-driven" design.
//
// Assignment.
// o Add a second pure virtual function to class FederalFraudvillian -
//      virtual FederalFraudvillian* clone() = 0;
// o Create a Factory base class with a single "virtual constructor" -
//      FederalFraudvillian* createPrevaricator( PrevaricatorType type )
// o Add the following enum declaration to the Factory class -
//      enum PrevaricatorType { None, PresT, AGT, MPCPT };
// o Add a protected array of FederalFraudvillian "prototypical instances" 
//   to the Factory class -
//      FederalFraudvillian* prototypes[4];
// o The body of the createPrevaricator() method will simply use its type
//   argument as an offset into the prototypes array, call clone() on that
//   prototypical instance, and return whatever clone() returns
// o Create two classes derived from Factory: DemocratFactory, and
//   RepublicanFactory
// o These two derived classes will only contain a default constructor.
//   Each constructor will populate the prototype array in the base class
//   with instances of the classes: 0, President, AttorneyGeneral, and
//   MinorityPartyCongressPerson.  Make sure these "prototypes" are of the
//   correct party affiliation.
// o Instantiate a factory object at the top of main() with code like -
//      #ifdef DEMOCRAT
//         Factory* factory = new DemocratFactory;
//      #else
//         Factory* factory = new RepublicanFactory;
//      #endif
// o Replace the calls to "new" in main() with a single call to -
//      createPrevaricator( in )
// o The "new"s that were being performed in main() will now be done
//   [indirectly] in the clone() method of each FederalFraudvillian derived
//   class
// o Add a 1-arg constructor to the FederalFraudvillian derived classes.
//   Use a "member initialization list" to map the char* argument the
//   constructor receives to the Base class's 1-arg constructor.
// o Add a clone() method to the FederalFraudvillian derived classes.  The
//   body of clone() should create an instance of the class it is a member of
//   (being careful to supply the char* argument the constructor is expecting)
//   and return the new instance.
// o Move as many declarations and definitions as possible below main() to
//   demonstrate the minimal coupling that remains

#include <iostream.h>
#include <string.h>

class FederalFraudvillian {
public:
   FederalFraudvillian( char* pp = "Democrat" ) { strcpy( party, pp ); }
   virtual void partyLine() = 0;
protected:
   char party[20];
};

class President : public FederalFraudvillian {
public:
   void partyLine() { cout << party << ": speak no evil" << endl; }
};

class AttorneyGeneral : public FederalFraudvillian {
public:
   void partyLine() { cout << party << ": see no evil" << endl; }
};

class MinorityPartyCongressPerson : public FederalFraudvillian {
public:
   void partyLine() { cout << party << ": hear no evil" << endl; }
};

void main( void ) {
   FederalFraudvillian*  moralMisfits[10];
   int      in, i, total = 0;

   cout << "President(1) AG(2) MPCP(3) Go(0): ";
   cin >> in;
   while (in) {
      if (in == 1)      moralMisfits[total++] = new President;
      else if (in == 2) moralMisfits[total++] = new AttorneyGeneral;
      else              moralMisfits[total++] = new MinorityPartyCongressPerson;
      cout << "President(1) AG(2) MPCP(3) Go(0): ";
      cin >> in;
   }
   for (i=0; i < total; i++) moralMisfits[i]->partyLine();
   for (i=0; i < total; i++) delete moralMisfits[i];
}

// no compiler directive -
// President(1) AG(2) MPCP(3) Go(0): 1
// President(1) AG(2) MPCP(3) Go(0): 2
// President(1) AG(2) MPCP(3) Go(0): 3
// President(1) AG(2) MPCP(3) Go(0): 1
// President(1) AG(2) MPCP(3) Go(0): 0
// Republican: speak no evil
// Republican: see no evil
// Republican: hear no evil
// Republican: speak no evil

// -DDEMOCRAT -
// President(1) AG(2) MPCP(3) Go(0): 1
// President(1) AG(2) MPCP(3) Go(0): 2
// President(1) AG(2) MPCP(3) Go(0): 3
// President(1) AG(2) MPCP(3) Go(0): 1
// President(1) AG(2) MPCP(3) Go(0): 0
// Democrat: speak no evil
// Democrat: see no evil
// Democrat: hear no evil
// Democrat: speak no evil

