11.6. Prototype

  • EN: Prototype

  • PL: Prototyp

  • Type: object

11.6.1. Pattern

  • Create new object by copying an existing object

../../_images/designpatterns-prototype-pattern.png

11.6.2. Problem

  • Violates Open/Close Principle

../../_images/designpatterns-prototype-problem.png
from abc import ABC, abstractmethod


class Component(ABC):
    @abstractmethod
    def render(self) -> None: ...


class Circle(Component):
    radius: int

    def set_radius(self, value: int) -> None:
        self.radius = value

    def get_radius(self) -> int:
        return self.radius

    def render(self) -> None:
        print('Rendering circle')


class ContextMenu:
    def duplicate(self, component: Component) -> None:
        if isinstance(component, Circle):
            source = component
            target = Circle()
            target.set_radius(source.get_radius())

11.6.3. Solution

../../_images/designpatterns-prototype-solution.png
from __future__ import annotations
from abc import ABC, abstractmethod


class Component(ABC):
    @abstractmethod
    def render(self) -> None: ...

    @abstractmethod
    def clone(self) -> Component: ...


class Circle(Component):
    radius: int

    def set_radius(self, value: int) -> None:
        self.radius = value

    def get_radius(self) -> int:
        return self.radius

    def clone(self) -> Component:
        new_circle = Circle()
        new_circle.set_radius(self.radius)
        return new_circle

    def render(self) -> None:
        print('Rendering circle')


class ContextMenu:
    def duplicate(self, component: Component) -> None:
        new_component = component.clone()

11.6.4. Assignments