
- C++ Home
- C++ Overview
- C++ Environment Setup
- C++ Basic Syntax
- C++ Comments
- C++ Hello World
- C++ Omitting Namespace
- C++ Tokens
- C++ Constants/Literals
- C++ Keywords
- C++ Identifiers
- C++ Data Types
- C++ Numeric Data Types
- C++ Character Data Type
- C++ Boolean Data Type
- C++ Variable Types
- C++ Variable Scope
- C++ Multiple Variables
- C++ Input Output Operations
- C++ Basic Input/Output
- C++ Cin
- C++ Cout
- C++ Manipulators
- Type System & Data Representation
- C++ Modifier Types
- C++ Storage Classes
- C++ Constexpr Specifier
- C++ Numbers
- C++ Enumeration
- C++ Enum Class
- C++ References
- C++ Date & Time
- C++ Operators
- C++ Operators
- C++ Arithmetic Operators
- C++ Relational Operators
- C++ Logical Operators
- C++ Bitwise Operators
- C++ Assignment Operators
- C++ sizeof Operator
- C++ Conditional Operator
- C++ Comma Operator
- C++ Member Operators
- C++ Casting Operators
- C++ Pointer Operators
- C++ Operators Precedence
- C++ Unary Operators
- C++ Scope Resolution Operator
- C++ Control Statements
- C++ Decision Making
- C++ if Statement
- C++ if else Statement
- C++ Nested if Statements
- C++ switch Statement
- C++ Nested switch Statements
- C++ Loop Types
- C++ while Loop
- C++ for Loop
- C++ do while Loop
- C++ Foreach Loop
- C++ Nested Loops
- C++ Jump Statements
- C++ break Statement
- C++ continue Statement
- C++ goto Statement
- C++ Return Values
- C++ Strings
- C++ Strings
- C++ Loop Through a String
- C++ String Length
- C++ String Concatenation
- C++ String Comparison
- C++ Functions
- C++ Functions
- C++ Multiple Function Parameters
- C++ Recursive Function
- C++ Function Overloading
- C++ Function Overriding
- C++ Default Arguments
- C++ Arrays
- C++ Arrays
- C++ Multidimensional Arrays
- C++ Pointer to an Array
- C++ Passing Arrays to Functions
- C++ Return Array from Functions
- C++ Structure & Union
- C++ Structures
- C++ Unions
- C++ Class and Objects
- C++ Object Oriented
- C++ Classes & Objects
- C++ Class Member Functions
- C++ Class Access Modifiers
- C++ Static Class Members
- C++ Static Data Members
- C++ Static Member Function
- C++ Inline Functions
- C++ this Pointer
- C++ Friend Functions
- C++ Pointer to Classes
- C++ Constructors
- C++ Constructor & Destructor
- C++ Default Constructors
- C++ Parameterized Constructors
- C++ Copy Constructor
- C++ Constructor Overloading
- C++ Constructor with Default Arguments
- C++ Delegating Constructors
- C++ Constructor Initialization List
- C++ Dynamic Initialization Using Constructors
- C++ Inheritance
- C++ Inheritance
- C++ Multiple Inheritance
- C++ Multilevel Inheritance
- C++ Object-oriented
- C++ Overloading
- C++ Polymorphism
- C++ Abstraction
- C++ Encapsulation
- C++ Interfaces
- C++ Virtual Function
- C++ Pure Virtual Functions & Abstract Classes
- C++ Design Patterns
- C++ Creational Design Patterns
- C++ Singleton Design Pattern
- C++ Factory Method Design Pattern
- C++ Abstract Factory Pattern
- C++ Prototype Design Pattern
- C++ Structural Design Patterns
- C++ File Handling
- C++ Files and Streams
- C++ Reading From File
- C++ Advanced
- C++ Exception Handling
- C++ Dynamic Memory
- C++ Namespaces
- C++ Templates
- C++ Preprocessor
- C++ Signal Handling
- C++ Multithreading
- C++ Web Programming
- C++ Socket Programming
- C++ Concurrency
- C++ Advanced Concepts
- C++ Lambda Expression
- C++ unordered_multiset
Prototype Design Pattern in C++
The Prototype Pattern is a part of the Creational Design Patterns family.
Consider a scenario where you have an object and your friend asks you to create its replica. How would you do that? You are probably thinking of creating a new object and then copying the values from the existing object to the new object. That is some good thinking! But, what if the existing objects have some fields that are private and not visible outside the class. And also, you would have to know the class of the existing object to create a new object of the same class, which makes your code dependent on the class of the object. In such cases, we need to use the Prototype Pattern.
The Prototype Pattern allows us to make copies from an actual object. It declares a common interface for all objects and those objects support cloning themselves. This means the object itself is responsible for creating a copy of itself. The client code can use the common interface to clone the object without knowing the class of the object. This interface has only one method, which is clone()
. The clone()
method is responsible for creating a copy of the object and returning it to the client code.
Whichever object that supports cloning is called a prototype. If your objects have too many feilds and many different types of configurations, then you can just clone them.
In the following image, an artist makes three different types of paintings. If someone wants a copy of one of the paintings, the artist can just clone the painting and give it to the person. The artist doesn't need to create a new painting from scratch. This is how the Prototype Pattern works.

Illustration of Prototype Pattern
Following is the illustration of Prototype Pattern. In the below image, we have a Client that wants to create a copy of an existing Prototype object. The Client uses the clone()
method of the Prototype to create a copy of the object without knowing the class of the object.

Implementation of Prototype Pattern in C++
We can implement the Prototype Pattern in the following two ways −
- Basic Prototype Pattern − This is the simple way without any registry.
- Prototype Pattern with Registry − This approach uses a registry to keep track of all prototypes.
1. Basic Prototype Pattern in C++
The following illustration shows the steps for implementing the Basic Prototype Pattern in C++

Example of Basic Prototype Pattern in C++
Let's implement a simple example of Basic Prototype Pattern in C++
Here we will take an example of a virtual machine class that supports cloning itself. The client will use the clone()
method of the VirtualMachine class to create a copy of the object.
#include <iostream> #include <memory> #include <string> using namespace std; // Prototype Interface class VirtualMachine { public: virtual unique_ptr<VirtualMachine> clone() const = 0; virtual void showConfig() const = 0; virtual ~VirtualMachine() = default; }; // Concrete Prototype: LinuxVM class LinuxVM : public VirtualMachine { string os; int ram; int cpu; public: LinuxVM(string os, int ram, int cpu) : os(move(os)), ram(ram), cpu(cpu) {} unique_ptr<VirtualMachine> clone() const override { cout << "Cloning Linux VM..." << endl; return make_unique<LinuxVM>(*this); // deep copy } void showConfig() const override { cout << "Linux VM - OS: " << os << ", RAM: " << ram << "GB, CPU: " << cpu << " cores" << endl; } }; // Concrete Prototype: WindowsVM class WindowsVM : public VirtualMachine { string os; int ram; int cpu; public: WindowsVM(string os, int ram, int cpu) : os(move(os)), ram(ram), cpu(cpu) {} unique_ptr<VirtualMachine> clone() const override { cout << "Cloning Windows VM..." << endl; return make_unique<WindowsVM>(*this); } void showConfig() const override { cout << "Windows VM - OS: " << os << ", RAM: " << ram << "GB, CPU: " << cpu << " cores" << endl; } }; // Client code int main() { // Create prototypes unique_ptr<VirtualMachine> linuxVM = make_unique<LinuxVM>("Ubuntu 20.04", 8, 4); unique_ptr<VirtualMachine> windowsVM = make_unique<WindowsVM>("Windows 10", 16, 8); //original objects cout << "Original VMs:" << endl; linuxVM->showConfig(); windowsVM->showConfig(); // Clone objects safely cout << "\nCloning VMs:" << endl; auto clonedLinuxVM = linuxVM->clone(); auto clonedWindowsVM = windowsVM->clone(); // Show configurations cout << "\nCloned VMs:" << endl; clonedLinuxVM->showConfig(); clonedWindowsVM->showConfig(); return 0; }
Following is the output of the above program −
Original VMs: Linux VM - OS: Ubuntu 20.04, RAM: 8GB, CPU: 4 cores Windows VM - OS: Windows 10, RAM: 16GB, CPU: 8 cores Cloning VMs: Cloning Linux VM... Cloning Windows VM... Cloned VMs: Linux VM - OS: Ubuntu 20.04, RAM: 8GB, CPU: 4 cores Windows VM - OS: Windows 10, RAM: 16GB, CPU: 8 cores
2. Prototype Pattern with Registry in C++
The following illustration shows the steps for implementing the Prototype Pattern with Registry in C++

Example of Prototype Pattern with Registry in C++
Let's implement a simple example of Prototype Pattern with Registry in C++:
Here we will take an example of making UI elements like Button and TextBox. We will create a Prototype Registry to keep track of all prototypes. The Client will use the registry to get the prototype and then clone whatever it wants.
#include <iostream> #include <memory> #include <string> #include <unordered_map> using namespace std; // Prototype Interface class UIElement { public: virtual unique_ptr<UIElement> clone() const = 0; virtual void render() const = 0; virtual ~UIElement() = default; }; // Concrete Prototype: Button class Button : public UIElement { string label; public: Button(string label) : label(move(label)) {} unique_ptr<UIElement> clone() const override { cout << "Cloning Button..." << endl; return make_unique<Button>(*this); // deep copy } void render() const override { cout << "Rendering Button: " << label << endl; } }; // Concrete Prototype: TextBox class TextBox : public UIElement { string text; public: TextBox(string text) : text(move(text)) {} unique_ptr<UIElement> clone() const override { cout << "Cloning TextBox..." << endl; return make_unique<TextBox>(*this); } void render() const override { cout << "Rendering TextBox: " << text << endl; } }; // Prototype Registry class PrototypeRegistry { unordered_map<string, unique_ptr<UIElement>> prototypes; public: void registerPrototype(const string& name, unique_ptr<UIElement> prototype) { prototypes[name] = move(prototype); } unique_ptr<UIElement> getPrototype(const string& name) const { auto it = prototypes.find(name); if (it != prototypes.end()) { return it->second->clone(); } return nullptr; } }; // Client code int main() { // Create registry and register prototypes PrototypeRegistry registry; registry.registerPrototype("Button", make_unique<Button>("Submit")); registry.registerPrototype("TextBox", make_unique<TextBox>("Enter your name")); // Clone objects safely using the registry cout << "Cloning UI Elements:" << endl; auto clonedButton = registry.getPrototype("Button"); auto clonedTextBox = registry.getPrototype("TextBox"); // Show configurations cout << "\nCloned UI Elements:" << endl; if (clonedButton) clonedButton->render(); if (clonedTextBox) clonedTextBox->render(); return 0; }
Following is the output of the above program −
Cloning UI Elements: Cloning Button... Cloning TextBox... Cloned UI Elements: Rendering Button: Submit Rendering TextBox: Enter your name
Key Properties of Prototype Pattern
Following are the key properties of the Prototype Pattern −
- Cloning, you can copy of existing objects. You don't need to create new objects from scratch.
- Decoupling, the client code is decoupled from the class of the object.
- Dynamic, you can add new prototypes at runtime.
- Can Create More than one type, you can create different types of objects using the same interface.
- Memory Usage, you can save memory by reusing existing objects instead of creating new ones.
Conclusion
In this chapter, we learned what is the Prototype Pattern and how to implement it in C++. We also saw two different ways of implementing the Prototype Pattern: Basic Prototype Pattern and Prototype Pattern with Registry. The Prototype Pattern is a powerful design pattern that allows us to create copies of existing objects without knowing their class. It helps in reducing memory usage and decoupling the client code from the class of the object.