Prototype Pattern

 Introduction:

Prototype design pattern is a creational design pattern. It allows us to create a copy of the existing object without creating the new instance.

How do we create a copy of the object? We create new object of the same class and start copying each field. But this direct approach has some issues. If the class has private fields, that can't be copied from outside of that class, also if we working with abstract class, we don't know about the concrete implementation.

This pattern delegates the cloning process to the actual object that is being cloned. This pattern provides the common interface "clone" to all the cloning object. The object which supports cloning process called prototype. The object which supports cloning process implements 'clone' method and creates its own copy.

When to use, 

  • When your code shouldn’t depend on the concrete classes of objects that you need to copy.
  • When your code shouldn’t depend on the concrete classes of objects that you need to copy.
  • When creating object is an expensive process.

How to use, 

  • Create prototype abstract class with clone() method.
  • Implement the clone() method in the class which supports cloning process.
  • Create a factory class which has the registry of prototype objects.
  • Design a factory method that: may (or may not) accept arguments, finds the correct prototype object, calls clone() on that object, and returns the result.
  • The client replaces all references to the new operator with calls to the factory method. 

UML Diagram:

Source: refactoring guru




















Implementation:

Sourcecode:https://github.com/krishnaKSA/design_patterns_cplusplus/blob/main/PrototypePattern/PrototypePattern.hpp

Class Diagram:










Prototype class:

    //Prototype class
    class Shape
    {
        private:
        int x;
        int y;
        string color;

        public:
        Shape(int x, int y, string color)
        {
            this->x = x;
            this->y = y;
            this->color = color;
        }
        void setColor(string color)
        {
            this->color = color;
        }
        string getColor()
        {
            return this->color;
        }

        virtual Shape* clone()=0;
    };

Concrete classes:


    //rectangle class
    class rectangle:public Shape
    {
        private:
        int length;
        int width;

        public:
        rectangle(int len, int wid, int x, int y, string color):Shape(x,y,color)
        {
            length = len;
            width = wid;
        }

        Shape* clone() override
        {
            return new rectangle(*this);
        }

    };

    //circle class
    class circle:public Shape
    {
        private:
        int radius;

        public:
        circle(int radius, int x, int y, string color):Shape(x,y,color)
        {
            this->radius = radius;
        }

        Shape* clone() override
        {
            return new circle(*this);
        }
    };

Factory class:

    //class shapefactory
    class ShapeFactory
    {
        private:
        vector<Shape*> circleList;
        vector<Shape*> rectangleList;
        Shape* pcircle;
        Shape* prectangle;

        public:
        ShapeFactory()
        {
            pcircle = new circle(10,1,2,"red");
            prectangle = new rectangle(10,20,1,2,"red");
        }
        void buildDifferntColorShapes(string color)
        {
            circleList.push_back(pcircle->clone());
            circleList.back()->setColor(color);
            rectangleList.push_back(prectangle->clone());
            rectangleList.back()->setColor(color);
        }

        void printList()
        {
            for(Shape* p:circleList)
            {
                printf("object color=%s \n",p->getColor().c_str());
            }
        }
    };

Client code:

    void testPrototypePattern()
    {
        ShapeFactory* factory = new ShapeFactory;
        factory->buildDifferntColorShapes("green");
        factory->buildDifferntColorShapes("yellow");
        factory->buildDifferntColorShapes("purple");
        factory->buildDifferntColorShapes("white");
        factory->buildDifferntColorShapes("black");
        factory->buildDifferntColorShapes("pink");
        factory->buildDifferntColorShapes("maroon");
        factory->printList();
    }