Python Prototype
Imagine you need to produce a batch of identical toy cars. Instead of designing and manufacturing from scratch each time, you would first create a perfect prototype, and then make copies based on this prototype. This is the core idea of the Prototype pattern!
**Prototype Pattern** is a creational design pattern that creates new objects by copying existing objects (prototypes) rather than instantiating them through classes. This approach is particularly suitable when the cost of creating objects is high, or when you need to create multiple similar objects.
### Why Do We Need the Prototype Pattern?
Let's first look at the problems with the traditional way of creating objects:
## Example
# Traditional approach - recreate every time
class Car:
def __init__ (self, brand, model, color, engine_type):
self.brand= brand
self.model= model
self.color= color
self.engine_type= engine_type
# Assume there is some complex initialization logic here
self.initialize_complex_components()
def initialize_complex_components(self):
# Simulate complex initialization process
import time
time.sleep(1)# Assume initialization takes 1 second
print(f"Initializing complex components for {self.brand} {self.model}...")
# Create multiple similar objects
car1 = Car("Toyota","Camry","Red","2.5L")
car2 = Car("Toyota","Camry","Blue","2.5L")# Need to re-execute complex initialization
**Disadvantages of the traditional approach:**
* Every object creation requires executing the full initialization process
* If initialization is complex, it consumes a lot of time and resources
* Code duplication, inefficient
* * *
## Implementation Principle of Prototype Pattern
The Prototype pattern solves the above problems by having objects responsible for creating their own copies. In Python, we can easily implement the Prototype pattern using the `copy` module.
### Core Components
!(#)
### Copy Mechanisms in Python
Python provides two types of copying:
| Copy Type | Method | Characteristics | Applicable Scenarios |
| --- | --- | --- | --- |
| **Shallow Copy** | `copy.copy()` | Only copies the object itself, not nested objects | Simple object structure, no nested references |
| **Deep Copy** | `copy.deepcopy()` | Copies the object and all nested objects | Complex object structure with nested references |
* * *
## Implementing the Prototype Pattern
Let's learn how to implement the Prototype pattern through a complete example.
### Basic Implementation
## Example
import copy
from abc import ABC, abstractmethod
from typing import Any
class Prototype(ABC):
"""Prototype abstract base class"""
@abstractmethod
def clone(self) -> Any:
"""Clone method - must be implemented by subclasses"""
pass
class CarPrototype(Prototype):
"""Car prototype class"""
def __init__ (self, brand: str, model: str, color: str, engine_type: str):
self.brand= brand
self.model= model
self.color= color
self.engine_type= engine_type
self.accessories=[]# Accessories list
self.initialize_complex_components()
def initialize_complex_components(self):
"""Simulate complex initialization process"""
print(f"Initializing complex components for {self.brand} {self.model}...")
# Here we can simulate some time-consuming initialization operations
def add_accessory(self, accessory: str):
"""Add accessory"""
self.accessories.append(accessory)
def clone(self) ->'CarPrototype':
"""Implement clone method - use deep copy"""
return copy.deepcopy(self)
def display_info(self):
"""Display car information"""
info = f"{self.brand} {self.model} - Color: {self.color}, Engine: {self.engine_type}"
if self.accessories:
info += f", Accessories: {', '.join(self.accessories)}"
print(info)
### Usage Example
## Example
# Create prototype object
print("=== Creating prototype object ===")
original_car = CarPrototype("Toyota","Camry","White","2.5L")
original_car.add_accessory("Navigation System")
original_car.add_accessory("Sunroof")
original_car.display_info()
print("n=== Creating new objects via cloning ===")
# Create new objects based on prototype
car1 = original_car.clone()
car1.color="Red"# Only modify color
car1.display_info()
car2 = original_car.clone()
car2.color="Blue"
car2.add_accessory("Leather Seats")# Add new accessory
car2.display_info()
# Verify prototype object is not modified
print("n=== Verifying prototype object is not modified ===")
original_car.display_info()
**Output:**
=== Creating prototype object ===Initializing complex components for Toyota Camry...Toyota Camry - Color: White, Engine: 2.5L, Accessories: Navigation System, Sunroof=== Creating new objects via cloning ===Toyota Camry - Color: Red, Engine: 2.5L, Accessories: Navigation System, SunroofToyota Camry - Color: Blue, Engine: 2.5L, Accessories: Navigation System, Sunroof, Leather Seats=== Verifying prototype object is not modified ===Toyota Camry - Color: White, Engine: 2.5L, Accessories: Navigation System, Sunroof
* * *
## Advanced Application Scenarios
### Scenario 1: Character Creation in Game Development
## Example
class GameCharacter(Prototype):
"""Game character prototype"""
def __init__ (self, name: str, character_class: str, level: int=1):
self.name= name
self.character_class= character_class
self.level= level
self.skills=[]
self.equipment={}
self.initialize_character()
def initialize_character(self):
"""Initialize character - simulate complex data loading"""
print(f"Loading character data for {self.name}...")
# Simulate loading data from database or config file
base_skills ={
"Warrior": ["Slash","Block","Charge"],
"Mage": ["Fireball","Ice Arrow","Teleport"],
"Archer": ["Precise Shot","Trap Setting","Quick Move"]
}
self.skills= base_skills.get(self.character_class,[])
def add_skill(self, skill: str):
"""Add skill"""
self.skills.append(skill)
def equip_item(self, slot: str, item: str):
"""Equip item"""
self.equipment= item
def clone(self) ->'GameCharacter':
"""Clone character"""
return copy.deepcopy(self)
def show_status(self):
"""Display character status"""
print(f"Character: {self.name} ({self.character_class}) - Level: {self.level}")
print(f"Skills: {', '.join(self.skills)}")
if self.equipment:
equipment_str =', '.join([f"{k}: {v}"for k, v in self.equipment.items()])
print(f"Equipment: {equipment_str}")
# Usage example
print("=== Game character prototype example ===")
warrior_template = GameCharacter("Warrior Template","Warrior")
warrior_template.equip_item("Weapon","Steel Longsword")
warrior_template.equip_item("Armor","Chainmail")
warrior_template.show_status()
print("n=== Creating player characters ===")
player1 = warrior_template.clone()
player1.name="Brave Adventurer"
player1.level=5
player1.add_skill("Whirlwind Slash")
player1.show_status()
player2 = warrior_template.clone()
player2.name="Fearless Guardian"
player2.level=3
player2.equip_item("Shield","Steel Shield")
player2.show_status()
### Scenario 2: Document Template System
## Example
class DocumentTemplate(Prototype):
"""Document template prototype"""
def __init__ (self, template_name: str):
self.template_name= template_name
self.headers={}
self.content_sections=[]
self.styles={}
self.load_template_config()
def load_template_config(self):
"""Load template configuration - simulate complex config loading"""
print(f"Loading template configuration for {self.template_name}...")
# Simulate loading configuration from file or database
self.headers={
"title": f"{self.template_name} Document",
"author": "System Generated",
"date": "2024-01-01"
}
self.styles={
"font_family": "Arial",
"font_size": "12pt",
"line_spacing": "1.5"
}
def clone(self) ->'DocumentTemplate':
"""Clone document template"""
return copy.deepcopy(self)
def customize(self, title: str=None, author: str=None):
"""Customize document"""
if title:
self.headers= title
if author:
self.headers= author
self.headers="2024-12-19"# Update date
def add_section(self, section_title: str, content: str):
"""Add content section"""
self.content_sections.append({
"title": section_title,
"content": content
})
def render(self):
"""Render document"""
print(f"n=== {self.headers['title']} ===")
print(f"Author:
YouTip