← 返回首页
🏭

创建型模式

📂 python ⏱ 4 min 635 words

创建型模式

创建型模式专注于对象的创建机制,将对象的创建与使用分离。本文将介绍三种高级创建型模式:建造者模式、原型模式和抽象工厂模式。

建造者模式

建造者模式将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。适用于创建过程复杂、步骤多的对象。

建造者实现

from typing import Optional, List

class HTTPRequest:
    """HTTP请求对象"""
    
    def __init__(self):
        self.method = "GET"
        self.url = ""
        self.headers: dict = {}
        self.body: Optional[str] = None
        self.timeout: int = 30
        self.retries: int = 0
    
    def __str__(self):
        return (f"HTTPRequest(method={self.method}, url={self.url}, "
                f"headers={self.headers}, timeout={self.timeout})")

class RequestBuilder:
    """HTTP请求建造者"""
    
    def __init__(self):
        self._request = HTTPRequest()
    
    def set_method(self, method: str) -> 'RequestBuilder':
        self._request.method = method.upper()
        return self
    
    def set_url(self, url: str) -> 'RequestBuilder':
        self._request.url = url
        return self
    
    def add_header(self, key: str, value: str) -> 'RequestBuilder':
        self._request.headers[key] = value
        return self
    
    def set_body(self, body: str) -> 'RequestBuilder':
        self._request.body = body
        return self
    
    def set_timeout(self, timeout: int) -> 'RequestBuilder':
        self._request.timeout = timeout
        return self
    
    def set_retries(self, retries: int) -> 'RequestBuilder':
        self._request.retries = retries
        return self
    
    def build(self) -> HTTPRequest:
        """构建最终的请求对象"""
        if not self._request.url:
            raise ValueError("URL不能为空")
        request = self._request
        self._request = HTTPRequest()  # 重置,支持重复使用
        return request

class RequestDirector:
    """请求Director,封装常见的请求构建过程"""
    
    @staticmethod
    def create_json_request(url: str, data: str) -> HTTPRequest:
        builder = RequestBuilder()
        return (builder
                .set_method("POST")
                .set_url(url)
                .add_header("Content-Type", "application/json")
                .set_body(data)
                .set_timeout(60)
                .build())
    
    @staticmethod
    def create_api_request(url: str, auth_token: str) -> HTTPRequest:
        builder = RequestBuilder()
        return (builder
                .set_method("GET")
                .set_url(url)
                .add_header("Authorization", f"Bearer {auth_token}")
                .add_header("Accept", "application/json")
                .set_retries(3)
                .build())

# 使用示例
request = (RequestBuilder()
           .set_method("PUT")
           .set_url("https://api.example.com/users/123")
           .add_header("Content-Type", "application/json")
           .add_header("Authorization", "Bearer token123")
           .set_body('{"name": "张三"}')
           .set_timeout(30)
           .build())
print(request)

# 使用Director创建标准请求
json_request = RequestDirector.create_json_request(
    "https://api.example.com/data",
    '{"key": "value"}'
)

原型模式

原型模式通过复制现有的对象来创建新对象,避免了重新初始化对象的开销。特别适合创建成本高的对象。

使用copy模块

import copy
from typing import Dict, List, Any

class Car:
    """汽车原型"""
    
    def __init__(self, model: str, color: str, features: List[str]):
        self.model = model
        self.color = color
        self.features = features.copy()
        self.engine = None
        self.transmission = None
    
    def clone(self, deep: bool = True) -> 'Car':
        """克隆汽车对象"""
        if deep:
            return copy.deepcopy(self)
        else:
            return copy.copy(self)
    
    def __str__(self):
        return (f"Car(model={self.model}, color={self.color}, "
                f"features={self.features})")

class CarPrototypeRegistry:
    """汽车原型注册表"""
    
    def __init__(self):
        self._prototypes: Dict[str, Car] = {}
    
    def register(self, name: str, car: Car):
        """注册原型"""
        self._prototypes[name] = car
    
    def clone(self, name: str, **kwargs) -> Car:
        """克隆原型并可选择性修改属性"""
        if name not in self._prototypes:
            raise ValueError(f"未找到原型: {name}")
        
        car = self._prototypes[name].clone()
        
        # 应用自定义属性
        for key, value in kwargs.items():
            setattr(car, key, value)
        
        return car

# 创建原型
base_sedan = Car("基础轿车", "白色", ["空调", "电动车窗"])
base_suv = Car("基础SUV", "黑色", ["空调", "电动车窗", "天窗", "导航"])

# 注册原型
registry = CarPrototypeRegistry()
registry.register("sedan", base_sedan)
registry.register("suv", base_suv)

# 从原型创建变体
custom_sedan = registry.clone("sedan", color="红色", features=["空调", "电动车窗", "真皮座椅"])
print(custom_sedan)  # Car(model=基础轿车, color=红色, features=['空调', '电动车窗', '真皮座椅'])

# 原型未被修改
print(base_sedan)  # Car(model=基础轿车, color=白色, features=['空调', '电动车窗'])

深拷贝与浅拷贝

import copy

class ComplexObject:
    """包含嵌套对象的复杂对象"""
    
    def __init__(self):
        self.simple_list = [1, 2, 3]
        self.nested_dict = {"key": [4, 5, 6]}
    
    def __str__(self):
        return f"list={self.simple_list}, dict={self.nested_dict}"

# 原始对象
original = ComplexObject()

# 浅拷贝 - 嵌套对象共享引用
shallow = copy.copy(original)
shallow.simple_list.append(4)
shallow.nested_dict["key"].append(7)

print(f"Original: {original}")  # list=[1, 2, 3], dict={'key': [4, 5, 6, 7]}
print(f"Shallow:  {shallow}")   # list=[1, 2, 3, 4], dict={'key': [4, 5, 6, 7]}

# 深拷贝 - 完全独立的副本
original2 = ComplexObject()
deep = copy.deepcopy(original2)
deep.simple_list.append(4)
deep.nested_dict["key"].append(7)

print(f"Original2: {original2}")  # list=[1, 2, 3], dict={'key': [4, 5, 6]}
print(f"Deep:      {deep}")       # list=[1, 2, 3, 4], dict={'key': [4, 5, 6, 7]}

抽象工厂模式

抽象工厂模式提供一个创建一系列相关对象的接口,而无需指定它们的具体类。

from abc import ABC, abstractmethod
from typing import Tuple

class Button(ABC):
    """按钮抽象类"""
    @abstractmethod
    def render(self) -> str:
        pass

class TextField(ABC):
    """文本框抽象类"""
    @abstractmethod
    def render(self) -> str:
        pass

class Checkbox(ABC):
    """复选框抽象类"""
    @abstractmethod
    def render(self) -> str:
        pass

class WindowsButton(Button):
    def render(self) -> str:
        return "[Windows按钮]"

class WindowsTextField(TextField):
    def render(self) -> str:
        return "(Windows文本框)"

class WindowsCheckbox(Checkbox):
    def render(self) -> str:
        return "☐ Windows复选框"

class MacButton(Button):
    def render(self) -> str:
        return "[Mac按钮]"

class MacTextField(TextField):
    def render(self) -> str:
        return "(Mac文本框)"

class MacCheckbox(Checkbox):
    def render(self) -> str:
        return "☑ Mac复选框"

class UIFactory(ABC):
    """UI工厂抽象类"""
    
    @abstractmethod
    def create_button(self) -> Button:
        pass
    
    @abstractmethod
    def create_text_field(self) -> TextField:
        pass
    
    @abstractmethod
    def create_checkbox(self) -> Checkbox:
        pass

class WindowsUIFactory(UIFactory):
    """Windows UI工厂"""
    
    def create_button(self) -> Button:
        return WindowsButton()
    
    def create_text_field(self) -> TextField:
        return WindowsTextField()
    
    def create_checkbox(self) -> Checkbox:
        return WindowsCheckbox()

class MacUIFactory(UIFactory):
    """Mac UI工厂"""
    
    def create_button(self) -> Button:
        return MacButton()
    
    def create_text_field(self) -> TextField:
        return MacTextField()
    
    def create_checkbox(self) -> Checkbox:
        return MacCheckbox()

class Dialog:
    """对话框,使用抽象工厂创建UI组件"""
    
    def __init__(self, factory: UIFactory):
        self.factory = factory
        self.button = factory.create_button()
        self.text_field = factory.create_text_field()
        self.checkbox = factory.create_checkbox()
    
    def render(self) -> str:
        return f"{self.button.render()} {self.text_field.render()} {self.checkbox.render()}"

# 根据平台选择工厂
import platform
factory = MacUIFactory() if platform.system() == "Darwin" else WindowsUIFactory()
dialog = Dialog(factory)
print(dialog.render())

模式对比

模式 适用场景 优点 缺点
建造者模式 创建过程复杂,需要多个步骤 灵活,可创建不同表示 增加复杂度
原型模式 对象创建成本高 性能好,避免重复初始化 深拷贝可能有问题
抽象工厂 需要创建一系列相关对象 一致性,易于扩展 添加新类型困难

创建型模式的选择取决于具体需求:简单对象用工厂方法,复杂对象用建造者,需要复用现有对象用原型,需要创建产品族用抽象工厂。