Prototype - shoonie/StudyingDesignPattern GitHub Wiki

Intent

Specify the kinds of objects to create using a prototypical instance, and create new objects by copying the prototype.

Diagram

disgram

Consequences

  1. Adding and removing products at run-time.
  2. Specifying new objects by varying values.
  3. Specifying new objects by varying structure.
  4. Reduced subclassing.
  5. Configuring an application with classes dynamically.

Implementation

  1. Using a prototype manager.
  2. Implementing the Clone operation.
  3. Initializing clones.

Sample Code

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;
const int N = 4;

// Prototype
class Document 
{
public:
   virtual Document* clone() const = 0;
   virtual void store() const = 0;
   virtual ~Document() { }
};

// Concrete prototypes : xmlDoc, plainDoc, spreadsheetDoc

class xmlDoc : public Document 
{
public:
   Document*   clone() const { return new xmlDoc; }
   void store() const { cout << "xmlDoc\n"; }
};

class plainDoc : public Document 
{
public:
   Document* clone() const { return new plainDoc; }
   void store() const { cout << "plainDoc\n"; }
};

class spreadsheetDoc : public Document 
{
public:
   Document* clone() const { return new spreadsheetDoc; }
   void store() const { cout << "spreadsheetDoc\n"; }
};

// makeDocument() calls Concrete Portotype's clone() method 
// inherited from Prototype
class DocumentManager {
public:
   static Document* makeDocument( int choice );
   ~DocumentManager(){}

private:
   static Document* mDocTypes[N];
};

Document* DocumentManager::mDocTypes[] = 
{
   0, new xmlDoc, new plainDoc, new spreadsheetDoc
};

Document* DocumentManager::makeDocument( int choice ) 
{
   return mDocTypes[choice]->clone();
}

// for_each op ()
struct Destruct
{
    void operator()(Document *a) const { 
	delete a; 
    }
};

// Client
int main() {
   vector<Document*> docs(N);
   int choice;
   cout << "quit(0), xml(1), plain(2), spreadsheet(3): \n";
   while (true) {
	  cout << "Type in your choice (0-3)\n";
	  cin >> choice;
      if (choice <= 0 || choice >= N)
         break;
      docs[choice] = DocumentManager::makeDocument( choice );
   }

   for (int i = 1; i < docs.size(); ++i) 
	   if(docs[i]) docs[i]->store();

   Destruct d;
    // this calls Destruct::operator()
    for_each(docs.begin(), docs.end(), d);

   return 0;
}
⚠️ **GitHub.com Fallback** ⚠️