Open In App

Prototype Design Pattern

Last Updated : 25 Sep, 2025
Comments
Improve
Suggest changes
30 Likes
Like
Report

The prototype pattern is a creational design pattern which is required when object creation is a time-consuming, and costly operation, so we create objects with the existing object itself to by copying the existing ones.

  • The newly copied object may change the same properties only if required. This approach saves costly resources and time, especially when object creation is a heavy process.
  • One of the best available ways to create an object from existing objects is the clone() method. Clone is the simplest approach to implementing a prototype pattern. However, it is your call to decide how to copy existing objects based on your business model.

Suppose a user creates a document with a specific layout, fonts, and styling, and wishes to create similar documents with slight modifications.

Real Life Software Examples

  • Document and Content Management Systems can use the prototype pattern to manage document templates. Users can clone an existing template and then make specific modifications.
  • Game engines can use to frequently clone complex characters or terrain objects. The Prototype approach allows efficient duplication without repeating costly initialization.

Components of Prototype Design Pattern

Components include the prototype interface or abstract class, concrete prototypes and the client code, and the clone method specifying cloning behavior.

PrototypeComponentdrawio-(2)

  • Prototype Interface or Abstract Class : This defines the method for cloning objects and sets a standard that all concrete prototypes must follow. It includes a clone method that concrete prototypes will implement to create copies of themselves.
  • Concrete Prototype : This class implements the prototype interface or extends the abstract class. It represents a specific type of object that can be cloned.
  • Client : The Client is the code or module that requests new object creation by interacting with the prototype.
  • Clone Method : This method is declared in the prototype interface or abstract class and outlines how an object should be copied. Concrete prototypes implement this to define their specific cloning behavior.

Example Implementation

Let's understand how prototype design pattern work with the help of an example:

Imagine you're working on a drawing application, and you need to create and manipulate various shapes. Each shape might have different attributes like color or size. Creating a new shape class for every variation becomes tedious. Also, dynamically adding or removing shapes during runtime can be challenging.

Let's understand how Prototype Design Pattern will help to solve this problem:

  • The Prototype Design Pattern helps in managing variations of shapes efficiently, promoting flexibility in shape creation, and simplifying the process of adding or removing shapes at runtime.
  • The Prototype Design Pattern addresses this by introducing a prototype interface (Shape) that declares common methods for cloning and drawing shapes.
  • Concrete prototypes like Circle implement this interface, providing their unique cloning logic.
  • The ShapeClient acts as a user, utilizing the prototype to create new shapes.

PrototypeDesignPatternExampledrawio-(2)

1. Prototype Interface (Shape):

We define an interface called Shape that acts as the prototype.It declares two methods: clone() for making a copy of itself and draw() for drawing the shape.

C++
#include <memory>

class Shape {
public:
    virtual std::unique_ptr<Shape> clone() const = 0;  // Make a copy of itself
    virtual void draw() const = 0;    // Draw the shape
};
Java
public interface Shape {
    Shape clone();  // Make a copy of itself
    void draw();    // Draw the shape
}
Python
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def clone(self):
        """Make a copy of itself"""
        pass

    @abstractmethod
    def draw(self):
        """Draw the shape"""
        pass
JavaScript
class Shape {
    clone() { /* Make a copy of itself */ }
    draw() { /* Draw the shape */ }
}


2. Concrete Prototype (Circle):

We implement the Shape interface with a concrete class Circle. The Circle class has a private field color and a constructor to set the color when creating a circle. It implements the clone() method to create a copy of itself (a new Circle with the same color). The draw() method is implemented to print a message indicating how the circle is drawn.

C++
#include <iostream>
#include <string>

class Shape {
public:
    virtual Shape* clone() const = 0;
    virtual void draw() const = 0;
};

class Circle : public Shape {
private:
    std::string color;
public:
    Circle(const std::string& color) : color(color) {}

    Shape* clone() const override {
        return new Circle(color);
    }

    void draw() const override {
        std::cout << "Drawing a " << color << " circle." << std::endl;
    }
};
Java
// This is a specific shape, a circle, implementing the Shape interface.
// It can create a copy of itself (clone) and draw in its own way.
public class Circle implements Shape {
    private String color;

    // When you create a circle, you give it a color.
    public Circle(String color) {
        this.color = color;
    }

    // This creates a copy of the circle.
    @Override
    public Shape clone() {
        return new Circle(this.color);
    }

    // This is how a circle draws itself.
    @Override
    public void draw() {
        System.out.println("Drawing a " + color + " circle.");
    }
}
Python
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def clone(self):
        pass

    @abstractmethod
    def draw(self):
        pass

class Circle(Shape):
    def __init__(self, color):
        self.color = color

    def clone(self):
        return Circle(self.color)

    def draw(self):
        print(f'Drawing a {self.color} circle.')
JavaScript
class Shape {
    clone() {
        throw new Error('Method not implemented.');
    }

    draw() {
        throw new Error('Method not implemented.');
    }
}

class Circle extends Shape {
    constructor(color) {
        super();
        this.color = color;
    }

    clone() {
        return new Circle(this.color);
    }

    draw() {
        console.log(`Drawing a ${this.color} circle.`);
    }
}


3. Client (ShapeClient):

We create a client class, ShapeClient, which will use the prototype to create new shapes. The client has a field shapePrototype representing the prototype it will use. The constructor takes a Shape prototype, and there's a method createShape() that creates a new shape using the prototype's clone() method.

C++
#include <iostream>
#include <memory>

// This is like a user of shapes.
// It uses a prototype (a shape) to create new shapes.
class Shape {
public:
    virtual std::unique_ptr<Shape> clone() const = 0;
};

class ShapeClient {
private:
    std::unique_ptr<Shape> shapePrototype;

public:
    // When you create a client, you give it a prototype (a shape).
    ShapeClient(std::unique_ptr<Shape> shapePrototype) : shapePrototype(std::move(shapePrototype)) {}

    // This method creates a new shape using the prototype.
    std::unique_ptr<Shape> createShape() {
        return shapePrototype->clone();
    }
};
Java
// This is like a user of shapes.
// It uses a prototype (a shape) to create new shapes.
public class ShapeClient {
    private Shape shapePrototype;

    // When you create a client, you give it a prototype (a shape).
    public ShapeClient(Shape shapePrototype) {
        this.shapePrototype = shapePrototype;
    }

    // This method creates a new shape using the prototype.
    public Shape createShape() {
        return shapePrototype.clone();
    }
}
Python
# This is like a user of shapes.
# It uses a prototype (a shape) to create new shapes.
from copy import copy

class Shape:
    def clone(self):
        return copy(self)

class ShapeClient:
    def __init__(self, shape_prototype):
        self.shape_prototype = shape_prototype

    # This method creates a new shape using the prototype.
    def create_shape(self):
        return self.shape_prototype.clone()
JavaScript
// This is like a user of shapes.
// It uses a prototype (a shape) to create new shapes.
class ShapeClient {
    constructor(shapePrototype) {
        this.shapePrototype = shapePrototype;
    }

    // This method creates a new shape using the prototype.
    createShape() {
        return this.shapePrototype.clone();
    }
}


4. Complete code for the above example:

In the main class, PrototypeExample, we create a concrete prototype (circlePrototype) of a red circle. We then create a ShapeClient and provide it with the red circle prototype. The client uses the prototype to create a new shape (redCircle) using the createShape() method. Finally, we draw the newly created red circle using its draw() method.

C++
#include <iostream>
#include <string>
using namespace std;

// Prototype interface
class Shape {
public:
    virtual Shape* clone() = 0;  // Make a copy of itself
    virtual void draw() = 0;    // Draw the shape
};

// Concrete prototype
class Circle : public Shape {
private:
    string color;

public:
    Circle(string color) : color(color) {}

    // This creates a copy of the circle.
    Shape* clone() override {
        return new Circle(this->color);
    }

    // This is how a circle draws itself.
    void draw() override {
        cout << "Drawing a " << color << " circle." << endl;
    }
};

// Client code
class ShapeClient {
private:
    Shape* shapePrototype;

public:
    ShapeClient(Shape* shapePrototype) : shapePrototype(shapePrototype) {}

    // This method creates a new shape using the prototype.
    Shape* createShape() {
        return shapePrototype->clone();
    }
};

// Main class
int main() {
    // Create a concrete prototype (a red circle).
    Shape* circlePrototype = new Circle("red");

    // Create a client and give it the prototype.
    ShapeClient client(circlePrototype);

    // Use the prototype to create a new shape (a red circle).
    Shape* redCircle = client.createShape();

    // Draw the newly created red circle.
    redCircle->draw();

    delete circlePrototype;
    delete redCircle;
    return 0;
}
Java
// Prototype interface
interface Shape {
    Shape clone();  // Make a copy of itself
    void draw();    // Draw the shape
}

// Concrete prototype
class Circle implements Shape {
    private String color;

    // When you create a circle, you give it a color.
    public Circle(String color) {
        this.color = color;
    }

    // This creates a copy of the circle.
    @Override
    public Shape clone() {
        return new Circle(this.color);
    }

    // This is how a circle draws itself.
    @Override
    public void draw() {
        System.out.println("Drawing a " + color + " circle.");
    }
}

// Client code
class ShapeClient {
    private Shape shapePrototype;

    // When you create a client, you give it a prototype (a shape).
    public ShapeClient(Shape shapePrototype) {
        this.shapePrototype = shapePrototype;
    }

    // This method creates a new shape using the prototype.
    public Shape createShape() {
        return shapePrototype.clone();
    }
}

// Main class
public class PrototypeExample {
    public static void main(String[] args) {
        // Create a concrete prototype (a red circle).
        Shape circlePrototype = new Circle("red");

        // Create a client and give it the prototype.
        ShapeClient client = new ShapeClient(circlePrototype);

        // Use the prototype to create a new shape (a red circle).
        Shape redCircle = client.createShape();

        // Draw the newly created red circle.
        redCircle.draw();
    }
}
Python
from abc import ABC, abstractmethod

# Prototype interface
class Shape(ABC):
    @abstractmethod
    def clone(self):
        """Make a copy of itself"""
        pass

    @abstractmethod
    def draw(self):
        """Draw the shape"""
        pass

# Concrete prototype
class Circle(Shape):
    def __init__(self, color):
        self.color = color

    # This creates a copy of the circle.
    def clone(self):
        return Circle(self.color)

    # This is how a circle draws itself.
    def draw(self):
        print(f'Drawing a {self.color} circle.')

# Client code
class ShapeClient:
    def __init__(self, shape_prototype):
        self.shape_prototype = shape_prototype

    # This method creates a new shape using the prototype.
    def create_shape(self):
        return self.shape_prototype.clone()

# Main class
if __name__ == '__main__':
    # Create a concrete prototype (a red circle).
    circle_prototype = Circle('red')

    # Create a client and give it the prototype.
    client = ShapeClient(circle_prototype)

    # Use the prototype to create a new shape (a red circle).
    red_circle = client.create_shape()

    # Draw the newly created red circle.
    red_circle.draw()
JavaScript
// Prototype interface
class Shape {
    clone() {}  // Make a copy of itself
    draw() {}    // Draw the shape
}

// Concrete prototype
class Circle extends Shape {
    constructor(color) {
        super();
        this.color = color;
    }

    // This creates a copy of the circle.
    clone() {
        return new Circle(this.color);
    }

    // This is how a circle draws itself.
    draw() {
        console.log(`Drawing a ${this.color} circle.`);
    }
}

// Client code
class ShapeClient {
    constructor(shapePrototype) {
        this.shapePrototype = shapePrototype;
    }

    // This method creates a new shape using the prototype.
    createShape() {
        return this.shapePrototype.clone();
    }
}

// Main class
(() => {
    // Create a concrete prototype (a red circle).
    const circlePrototype = new Circle('red');

    // Create a client and give it the prototype.
    const client = new ShapeClient(circlePrototype);

    // Use the prototype to create a new shape (a red circle).
    const redCircle = client.createShape();

    // Draw the newly created red circle.
    redCircle.draw();
})();

Output:

Output
Drawing a red circle.

When to use the Prototype Design Pattern 

Below is when to use prototype design pattern:

  • Use the Prototype pattern when creating new objects is more complex or costly than copying existing ones. Cloning can be more efficient if significant resources are needed.
  • The Prototype pattern is helpful for managing various objects with minor differences. Instead of creating multiple classes, you can clone and modify prototypes.
  • Consider the Prototype pattern for dynamic configurations where you need to create objects at runtime. You can clone a base configuration and adjust it as necessary.
  • The Prototype pattern can lower initialization costs, as cloning is often faster than building a new object from scratch, especially if initialization is resource-intensive.

When not to use the Prototype Design Pattern 

Below is when not to use Prototype design pattern:

  • Avoid using the Prototype pattern when your application predominantly deals with unique object instances, and the overhead of implementing the pattern outweighs its benefits.
  • If object creation is simple and does not involve significant resource consumption, and there are no variations of objects, using the Prototype pattern might be unnecessary complexity.
  • If your objects are immutable (unchangeable) and do not need variations, the benefits of cloning may not be significant.
  • If your system has a clear and straightforward object creation process that is easy to understand and manage, introducing the Prototype pattern may add unnecessary complexity.

Explore