Prototype in Python
Prototype is a creational design pattern that allows cloning objects, even complex ones, without coupling to their specific classes.
All prototype classes should have a common interface that makes it possible to copy objects even if their concrete classes are unknown. Prototype objects can produce full copies since objects of the same class can access each other’s private fields.
Learn more about Prototype
Usage of the pattern in Python
Usage examples: The Prototype pattern is available in Python out of the box with a
Identification: The prototype can be easily recognized by a
copy() methods, etc.
This example illustrates the structure of the
Prototype design pattern. It focuses on answering these questions:
What classes does it consists of?
What roles do these classes play?
In what way the elements of the pattern are related?
main.py: Conceptual Example
from __future__ import annotations
from datetime import datetime
from copy import deepcopy
from typing import Any
The example class that has cloning ability. We'll see how the values of
field with different types will be cloned.
def __init__(self) -> None:
self._primitive = None
self._component = None
self._circular_reference = None
def primitive(self) -> Any:
def primitive(self, value: Any) -> None:
self._primitive = value
def component(self) -> object:
def component(self, value: object) -> None:
self._component = value
def circular_reference(self) -> ComponentWithBackReference:
def circular_reference(self, value: ComponentWithBackReference) -> None:
self._circular_reference = value
def clone(self) -> Prototype:
self.component = deepcopy(self.component)
# Cloning an object that has a nested object with backreference requires
# special treatment. After the cloning is completed, the nested object
# should point to the cloned object, instead of the original object.
self.circular_reference = deepcopy(self.circular_reference)
self.circular_reference.prototype = self
def __init__(self, prototype: Prototype):
self._prototype = prototype
def prototype(self) -> Prototype:
def prototype(self, value: Prototype) -> None:
self._prototype = value
if __name__ == "__main__":
# The client code.
p1 = Prototype()
p1.primitive = 245
p1.component = datetime.now()
p1.circular_reference = ComponentWithBackReference(p1)
p2 = p1.clone()
if p1.primitive is p2.primitive:
print("Primitive field values have been carried over to a clone. Yay!")
print("Primitive field values have not been copied. Booo!")
if p1.component is p2.component:
print("Simple component has not been cloned. Booo!")
print("Simple component has been cloned. Yay!")
if p1.circular_reference is p2.circular_reference:
print("Component with back reference has not been cloned. Booo!")
print("Component with back reference has been cloned. Yay!")
if p1.circular_reference.prototype is p2.circular_reference.prototype:
print("Component with back reference is linked to original object. Booo!", end="")
print("Component with back reference is linked to the clone. Yay!", end="")
Output.txt: Execution result
Primitive field values have been carried over to a clone. Yay!
Simple component has been cloned. Yay!
Component with back reference has been cloned. Yay!
Component with back reference is linked to the clone. Yay!
Prototype in Other Languages