The
Protoype pattern is used when creating an instance of a class is very time-consuming or complex in some way. Then, rather than creating more instances, you make copies of the original instance, modifying them as appropriate.
Prototypes can also be used whenever you need classes that differ only in the type of processing they offer, for example in parsing of strings representing numbers in different radixes. This design pattern is
not used very frequently.
The following is an example of Prototype Design Pattern:
#include <iostream>
#include <string>
#include <iomanip>
#include <map>
using namespace std;class ColourPrototype
{
public:
virtual ColourPrototype* Clone(void) = 0;
};class Colour : public ColourPrototype
{
public:
Colour(int red, int green, int blue)
{
red_ = red, green_ = green, blue_ = blue;
}
ColourPrototype* Clone(void)
{
cout << "Cloning colour RGB: " << setw(3) << red_ << ", " << setw(3) << green_ <<", " << setw(3) << blue_ <<endl;
ColourPrototype* colourPrototype = new Colour(red_, green_, blue_);
return colourPrototype;
}
void SetRed(int red)
{
red_ = red;
}
void SetGreen(int green)
{
green_ = green;
}
void SetBlue(int blue)
{
blue_ = blue;
}
int GetRed(void)
{
return red_;
}
int GetGreen(void)
{
return green_;
}
int GetBlue(void)
{
return blue_;
}
private:
Colour(); int red_, green_, blue_;
};class ColourManager
{
public:
virtual ~ColourManager()
{
while(!coloursMap_.empty())
{
map<string, ColourPrototype*>::iterator it = coloursMap_.begin();
delete it->second;
coloursMap_.erase(it);
}
}
void AddColour(const string& colour, ColourPrototype* prototype)
{
coloursMap_[colour] = prototype;
}
ColourPrototype* GetColour(const string& colour)
{
map<string, ColourPrototype*>::const_iterator it = coloursMap_.find(colour);
if(it != coloursMap_.end())
return it->second;
return NULL;
}
void PrintColours(void)
{
cout << "\nAvailable Colours and their values " << endl;
map<string, ColourPrototype*>::const_iterator it = coloursMap_.begin();
while(it != coloursMap_.end())
{
cout << setw(20) << it->first << " : ";
cout << setw(3) << dynamic_cast<Colour*>(it->second)->GetRed() << ", ";
cout << setw(3) << dynamic_cast<Colour*>(it->second)->GetGreen() << ", ";
cout << setw(3) << dynamic_cast<Colour*>(it->second)->GetBlue() << endl;
++it;
}
}
private:
map<string, ColourPrototype*> coloursMap_;
};int main()
{
ColourManager* colourManager = new ColourManager(); colourManager->AddColour("Red", new Colour(255, 0, 0));
colourManager->AddColour("Green", new Colour(0, 255, 0));
colourManager->AddColour("Blue", new Colour(0, 0, 255)); colourManager->AddColour("Angry", new Colour(255, 54, 0));
colourManager->AddColour("Peace", new Colour(128, 211, 128));
colourManager->AddColour("Flame", new Colour(211, 34, 20)); ColourPrototype* colour1 = (colourManager->GetColour("Red"))->Clone();
(dynamic_cast<Colour*>(colour1))->SetRed(200);
colourManager->AddColour("Light Red", colour1);
ColourPrototype* colour2 = (colourManager->GetColour("Peace"))->Clone();
(dynamic_cast<Colour*>(colour2))->SetRed(150);
(dynamic_cast<Colour*>(colour2))->SetBlue(150);
colourManager->AddColour("Extreme Peace", colour2);
ColourPrototype* colour3 = (colourManager->GetColour("Flame"))->Clone();
(dynamic_cast<Colour*>(colour3))->SetRed(255);
colourManager->AddColour("Hot Flame", colour3);
colourManager->PrintColours(); delete colourManager;
return 0;
}
The output is as follows:
Other good example of Prototype is available
here and
here.