Builder Design Pattern
December 17, 2012
Object pool design pattern
December 20, 2012

Prototype Design Pattern

Think of an Interior decorator. He will be performing the below two steps to suggest the decoration of interior to any client:

prototype

For each client that comes to the designer, he will do the above two steps.
The second step (designing the hall) is customized according to requirements of the client, but first step (creating raw hall) is same for everyone. Hence it makes a perfect sense to have it ready as a prototype (i.e clone the same object of the class).

In the above example we will have a class for room which will have a clone function.

rawroom

The designer will call this function to create the clone of a room and then will use that room to ocreate customized design.
This is nothing but the Prototype design pattern.
The prototype pattern is a Creational design pattern used when the type of objects to create is determined by a prototypical instance, that is cloned to produce new objects.
Class diagram:

prototype_classdiagram

Main classes:

  1. Client: Creates a new object by asking a prototype to clone itself (at least one object should already exist – which will be cloned).
  2. Prototype: The abstract base class of the product which can be clonned. Defines a clone virtual function (interface for cloning itself).
  3. ConcretePrototype: Implements the Prototype class and has operation for cloning itself. This is the actual product class.

Example:

prototype_example

The ImageHandler class manages the images and copy of Images. User can either create a clone of HomeImage or OfficeImage. It keeps a registry of already created objects of which clone function will be called to create a copy.

Code:

// Prototype Class
class Prototype
{
  public:
    // Virtual destructor should always be defined in a base class
    virtual ~Prototype() { }
    virtual Prototype* clone() const = 0;
};
// Concrete prototype class
class ConcretePrototype : public Prototype
{
  private:
    int data;
  public:
    // Default Constructor
    ConcretePrototype(int x) : data(x) { }
    // Copy constructor
    ConcretePrototype(const ConcretePrototype& p) : data(p.data) { }
    // Implementing the clone function of Base class.
    virtual Prototype* clone() const {
        // since we are copying we need to define Copy Constructor.
        return new ConcretePrototype(*this);
    }
    void setData(int x) {
        data = x;
    }
    int getData() const {
        return data;
    }
    void printData() const { std::cout << "Value :" << data << std::endl; }
};
// Client code
int main()
{
    // Creating the main Product (which will be cloned)
    Prototype* prototype = new ConcretePrototype(1000);
    for (int i = 1; i < 10; i++) {
        ConcretePrototype* obj = dynamic_cast<ConcretePrototype*>(prototype->clone());
        obj->setData( obj->getData() * i);
        obj->printData();
        delete obj;
    }
    delete prototype;
}

When to use Prototype pattern:

Whenever you see yourself creating object and then initializing it in similar way think of using the same configuration as Base configuration and use Prototype Pattern.

Leave a Reply

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