Prototype Design Pattern: Creational Patterns

Share the Article

What

Prototype design pattern is a type of creational pattern. This pattern helps to create a new object by cloning an existing object. The pre-condition is that there must be an existing object, which can be treated as prototype of that class. This pattern is used when creation of a new object from scratch is expensive but creation by copying from the given prototype object is cheap.

The prototype design pattern gives flexibility to the user to clone existing object and modify its properties as per need. This approach saves costly resources and time, especially, when the creation is a heavy process.

Why

Let us understand the need of Prototype pattern by taking an example. Here, we shall demonstrate an application which creates Computer class.

Computer is an expensive object to create at runtime. This is because it needs, lot of resources and time. For creation of an object, we need to select parts, for example, keyboard, mouse, CPU, screen, etc.

Application demonstrating creation of “Computer” without Prototype

#include<iostream> //main header using namespace std;//for namespace class Computer { public: Computer(string keyboard,string mouse, string processor): m_keyBoard(keyboard), m_mouse(mouse), m_processor(processor) { } virtual void ComputerCreated()=0; private: string m_keyBoard; string m_mouse; string m_processor; }; class BasicComputer: public Computer { protected: string m_ScreenType; public: BasicComputer(string keyboard,string mouse, string processor, string ScreenType): Computer(keyboard,mouse,processor), m_ScreenType(ScreenType) { } void ComputerCreated() { cout<< "Basic Computer created with"<<endl; cout<<"Keyboard "<<m_keyBoard<<endl; cout<<"Mouse "<<m_mouse<<endl; cout<<"Processor "<<m_processor<<endl; cout<<" Screen "<<m_ScreenType<<endl; } }; class SmartComputer: public Computer { private: string m_ScreenType; string m_Network; public: SmartComputer(string keyboard,string mouse, string processor, string ScreenType, string Network): Computer(keyboard,mouse,processor), m_ScreenType(ScreenType), m_Network(Network) { } void ComputerCreated() { cout<< "Smart Computer created with"<<endl; cout<<"Keyboard "<<m_keyBoard<<endl; cout<<"Mouse "<<m_mouse<<endl; cout<<"Processor "<<m_processor<<endl; cout<<" Screen "<<m_ScreenType<<endl; cout<<" Network "<<m_Network<<endl; } }; int main() { Computer *c1 = new BasicComputer(" wired","wired", "singleCore","Basic Screen"); c1->ComputerCreated(); Computer *c2 = new SmartComputer("wireless","wireless", "Dualcore"," Touch Screen", "WIFI"); c2->ComputerCreated(); }

In above example earlier we have Computer Base class and we have derived BasicComputer and SmartComputer from this.

During runtime, the user is creating all components of Basic and Smart Computer by selecting keyboard ,mouse screen, etc. All this is getting expensive operation at user-end. Therefore, the user is having all the burden of selecting and creating the classes.

Prototype design pattern is the best fit for above application .

How

Let us update above Computer application with Prototype design pattern. We shall follow some rules:

Create Abstract Base Class with a pure virtual function clone( )

class Computer { public: virtual Computer* Clone() = 0; };

Implement clone( ) function in Derived classes

Any new class, such as, BasicComputer or SmartComputer, which user wants shall inherit from Computer. These derived classes shall implement clone( ) function.

class BasicComputer : public Computer { public: Computer* Clone() { return new BasicComputer(*this); } };

In the below example, for easy explanation created Global object for BasicComputer and SmartComputer. Ideally, same can be created with Factory pattern also.

Example using prototype design pattern

#include<iostream> //main header using namespace std; //for namespace class Computer { public: Computer(string keyboard, string mouse, string processor): m_keyBoard(keyboard), m_mouse(mouse), m_processor(processor) { } virtual void ComputerCreated()=0; virtual Computer* Clone()=0; private: string m_keyBoard; string m_mouse; string m_processor; }; class BasicComputer: public Computer { protected: string m_ScreenType; public: BasicComputer(string keyboard, string mouse, string processor, string ScreenType): Computer(keyboard,mouse,processor), m_ScreenType(ScreenType) { } void ComputerCreated() { cout<< "Basic Computer created with"<<endl; cout<<"Keyboard "<<m_keyBoard<<endl; cout<<"Mouse "<<m_mouse<<endl; cout<<"Processor "<<m_processor<<endl; cout<<" Screen "<<m_ScreenType<<endl; } Computer* Clone() { return new BasicComputer(*this); } }; class SmartComputer: public Computer { string m_ScreenType; string m_Network; public: SmartComputer(string keyboard,string mouse, string processor,string ScreenType, string Network): Computer(keyboard,mouse,processor), m_ScreenType(ScreenType), m_Network(Network) { } void ComputerCreated() { cout<< "Smart Computer created with"<<endl; cout<<"Keyboard "<<m_keyBoard<<endl; cout<<"Mouse "<<m_mouse<<endl; cout<<"Processor "<<m_processor<<endl; cout<<" Screen "<<m_ScreenType<<endl; cout<<" Network "<<m_Network<<endl; } Computer *Clone() { return new SmartComputer(*this); } }; enum ComputerType { Basic=0, Smart }; //Prototypes of Objects Computer* ComputerObject[2] = { new BasicComputer("wired","wired", "single core","basic"), new SmartComputer("wireless","wireless", "Dual Core","Touch", "Wifi") }; Computer * CreateComputer(ComputerType computerType) { return ComputerObject[computerType]->Clone(); } int main() //Client code { Computer *c1 = CreateComputer(Basic); c1->ComputerCreated(); Computer *c2 = CreateComputer(Smart); c2->ComputerCreated(); }

In above example now we can see that Client code, i.e., Main function, is not creating an object from Scratch. Instead, the prototype objects already exists for all classes. Here, the Global function CreateComputer calls clone( ) member of requested type.

Basically, the client only needs to inform CreateComputer( ) method what type of Computer it requires. After this, the CreateComputer( ) function calls clone( ) function which uses the prototype and copy constructor to create object. If required, the client can modify existing object also.

Pros

  1. Firstly, it saves time and cost for object creation .
  2. It gives flexibility to enhance existing prototype. Also, it is possible to add or remove prototypes at runtime.
  3. Supports creation of complex object with less effort.

Cons

  1. The client may not like any of the available prototype objects. Probably, they might require specific modifications which are not possible.
  2. This method may prove expensive of all sub-classes are not complex to create.

Main Funda: Prototype design pattern is useful for creation of complex objects.

Advanced C++ Topics

Abstract Factory Design Pattern
Singleton Design Pattern
Factory Method Design Pattern
Builder Design Pattern
Adapter Design Pattern
How std::forward( ) works?
How std::move() function works?
What is reference collapsing?

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *