YouTip LogoYouTip

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:
← Python DecoratorPython Singleton β†’