Prototype design pattern for beginners.

Problem statement –

Let us first see what problem we are facing without prototype. There are so many places, where you must have used themes to change look and feel of screen. i.e –
1.       Changing theme of your mobile screen or your desktop screen.
2.       Changing theme of your FB page or Gmail page.
3.       Changing theme of e-greeting card.
Many more ….

Recollect your memory on theme, on a single theme we can have many colors. In many cases we have limited themes but with many colors option available, for example –
1.       Romantic theme (in 7 colors).
2.       Patriotic theme (in 7 colors).
3.       Warrior theme (in 7 colors).

Please understand, creating a theme is costly operation. It has to apply specific query and fetch data from DB and construct object with proper layout information.

For example, I have selected patriotic theme for my Gmail page, by default it comes with white background color. I am not liking it in white background, I don’t want to change theme, but I want to change it's color to red.

If we don’t use prototyping, we will create a new object of patriotic theme every time with different background color, with all costly operation again. But if you notice, we have old theme with color white in hand, all other properties like – layout, look and feels are same, still we have created patriotic theme object with red color from scratch which is not a good programming practice.

What we could have done here?

Create patriotic theme object only once, store it in some cache memory. Make a copy of existing default patriotic theme object (which we have already created once), without having any costly DB search on basis of patriotic theme (as all info are available in object’s memory now) and change color to red in new object.

No problem if you are not liking this particular example, think of any complex object creation according to your IT experience. If we have to create very similar object again and again with little or no properties changes, then it is a good idea to clone existing object (and apply changes on to the copy of object) instead of creating new object every time. 

When do we use prototype design pattern –

Whenever we are applying very expensive operations (or calculations) while creating the object.
      
       In some big applications before crating object we may have to query many things in DB, or stable connections to various hardware machines, for making system up and running.

Think if we have requirement to create different objects of same type. We should take reference to already created object, copy its all properties to new object, and apply new property changes on the basis of business logic to, newly created object. 

What is the difference between prototype and copay constructor in C++ -

If we think only from cloning prospective, of one type, then yes you may get confuse between copy constructor and prototype, but here we are talking about a polymorphic cloning on the basis of type of object. In Cpp, can I have a virtual constructor? No. It will through a compilation error, we should know the type of object during compilation otherwise it will throw an error. But what if I want to achieve virtual constructor in cpp? 

One of they way we can achieve virtual constructor through prototype design pattern.

apart form cloning we may have to add some more functionality like changing the behavior of cloned object through some manager class. which will be very easy if we apply prototype design pattern.

your code will become more manageable and understandable with prototype, otherwise you have to implement cloning and changing, and it's behavior, for each and every individually class level, and you will introduce more lines of code, which will end up with more numbers of bug, and you have to manage it, per class basis, not a good way to do, isn't it?

UML Structure -



C++ Example -





 /**************************************************************************************
 /* this code is to represent prototype design pattern.
 /*
 /* (c) 2016 Kunjesh Singh Baghel, All Rights Reserved.
 /* https://sites.google.com/site/kunjeshsinghbaghel/
 ***************************************************************************************/
 
 //*************************************************************************************
 // Header files
 #include<iostream>
 #include<string>
 #include<map>
 using namespace std;
 //*************************************************************************************
 //Global variables and functions 
 const string ROMANTIC = "RomanticTheme";
 const string PATRIOTIC = "PatrioticTheme";
 const string WARRIOR = "WarriorTheme";

 //*************************************************************************************
 // Class
 class ITheme
 {
  public:
  virtual ITheme* clone() = 0;
  virtual void draw() = 0;
  virtual string getThemeName() = 0;
  virtual string getColorName() = 0;
  virtual void setColor(string color) = 0;
 };

 //*************************************************************************************
 // Class
 class RomanticTheme : public ITheme
 {
  public:
  RomanticTheme(string color = "White"):m_color(color){}
  
  ITheme* clone()
  {
   return new RomanticTheme(*this);
  }
  
  void draw()
  {
   cout<< "Drowing RomanticTheme in " << m_color << " color " << endl;
  }
  string getThemeName()
  {
   return "RomanticTheme";
  }
  string getColorName()
  {
   return m_color;
  }
  void setColor(string color)
  {
   m_color = color;
  }
  private:
  string m_color;
 };
 
 //*************************************************************************************
 // Class
 class PatrioticTheme : public ITheme
 {
  public:
  PatrioticTheme(string color = "White"):m_color(color){}
  
  ITheme* clone()
  {
   return new PatrioticTheme(*this);
  }
  
  void draw()
  {
   cout<< "Drowing PatrioticTheme in " << m_color << " color " << endl;
  }
  string getThemeName()
  {
   return "PatrioticTheme";
  }
  string getColorName()
  {
   return m_color;
  }
  void setColor(string color)
  {
   m_color = color;
  }
  private:
  string m_color;
 };
 
 //*************************************************************************************
 // Class
 class WarriorTheme : public ITheme
 {
  public:
  WarriorTheme(string color = "White"):m_color(color){}
  
  ITheme* clone()
  {
   return new WarriorTheme(*this);
  }
  
  void draw()
  {
   cout<< "Drowing WarriorTheme in " << m_color << " color " << endl;
  }
  string getThemeName()
  {
   return "WarriorTheme";
  }
  string getColorName()
  {
   return m_color;
  }
  void setColor(string color)
  {
   m_color = color;
  }
  private:
  string m_color;
 };
 
 //*************************************************************************************
 // Class
 class ThemeManager
 {
  public:
  ThemeManager():m_themeAdded(false) {}
  void addTheme();
  ITheme* getTheme(string theme);
  ITheme* getTheme(string theme , string color);
  private:
  map<string, ITheme*> m_dictionary;
  bool m_themeAdded;
 };
 ///////////////////////////////////////////////////////////////////////////////////////
 void ThemeManager::addTheme() 
 {
    // first we have all available themes in our dictionary 
  m_dictionary.insert(pair<string, ITheme*>(ROMANTIC, (new RomanticTheme)));
  m_dictionary.insert(pair<string, ITheme*>(PATRIOTIC, (new PatrioticTheme)));
  m_dictionary.insert(pair<string, ITheme*>(WARRIOR, (new WarriorTheme)));
 }
 ///////////////////////////////////////////////////////////////////////////////////////
 ITheme* ThemeManager::getTheme(string theme)
 {
  if(!m_themeAdded)
  {
   addTheme();
  }   
  map<string, ITheme*>::iterator it = m_dictionary.find(theme);
  return it->second->clone();
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////
 ITheme* ThemeManager::getTheme(string theme, string color)
 {
  if(!m_themeAdded)
  {
   addTheme();
  } 
  map<string, ITheme*>::iterator it = m_dictionary.find(theme);
  it->second->setColor(color);
  return it->second->clone();
 }
 //*************************************************************************************
 // Main functions 
 int main(int argc, char** argv)
 {
  ThemeManager themeManagerObj;
  themeManagerObj.addTheme();
  ITheme *iThemePtr = themeManagerObj.getTheme("PatrioticTheme");
  iThemePtr->draw();
  
  ITheme *iThemePtr02 = themeManagerObj.getTheme("PatrioticTheme", "Red");
  iThemePtr02->draw();
  
  return 0;
 }

 
 ///////////////////////////////////////////////////////////////////-------------OutPut
 /*
  $ ./a.exe
  Drowing PatrioticTheme in White color
  Drowing PatrioticTheme in Red color

 */



Thanks for reading it. To read more on design patterns and basic design principles please see my web page. You can also join me on FB or on G++. Please drop comments for any question related to this blog.

Comments

Popular posts from this blog

Non-virtual interface idiom (NVI)

Factory method design pattern for beginners.

Architectural patterns => Mud to structure => layers.