Prototype Design Pattern (original) (raw)

Last Updated : 17 Apr, 2026

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.

**Example: Consider a Game Character System where creating a character involves loading graphics, skills, and configurations.

character

Prototype pattern

Instead of creating a new character from scratch every time:

Real Life Software Examples

Many modern applications use the Builder Pattern to improve flexibility and maintainability in object creation.

1. Document and Content Management Systems

Systems that manage, store, and reuse digital documents and templates efficiently.

2. Game Engines

Software frameworks used to create and manage game objects, characters, and environments.

Components

The pattern is built using multiple components that ensure flexible and controlled object creation.

class_diagram_of_prototype_design_pattern

Components

Features

The Prototype pattern enables efficient object creation through duplication.

Uses

The Prototype pattern is useful when object creation is costly or complex.

Implementation Example

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.

Solving this problem with the help of Prototype Design Pattern:

class_diagram_of_above_example

Class Diagram

1. Prototype Interface (Shape):

Defines the blueprint for cloning and drawing shapes.

#include

class Shape { public: virtual std::unique_ptr 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):

Implements the Shape interface and represents a specific shape.

#include #include

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):

Uses the prototype to create new shape objects.

#include #include

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

class ShapeClient { private: std::unique_ptr shapePrototype;

public: // When you create a client, you give it a prototype (a shape). ShapeClient(std::unique_ptr 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. Main Class (PrototypeExample):

Creates a concrete prototype (circlePrototype) with predefined properties.

#include #include 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

Drawing a red circle.

Advantages

The Prototype pattern improves performance and flexibility in object creation.

Disadvantages

Although efficient, the Prototype pattern introduces certain challenges.