# 创建型设计模式 创建型模式处理对象的创建机制,试图以适合当前情境的方式创建对象。 --- ## 1. 单例模式(Singleton Pattern) ### 问题 你需要一个类的唯一实例(例如,数据库连接、配置管理器、日志记录器)。 ### 反面示例 ```python # 可以创建多个实例 class DatabaseConnection: def __init__(self): self.connection = self.connect() def connect(self): print("Connecting to database...") return "DB Connection" # 问题:创建了多个连接 db1 = DatabaseConnection() db2 = DatabaseConnection() print(db1 is db2) # False — 不同的实例! ``` ### 解决方案 ```python class Singleton: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance class DatabaseConnection(Singleton): def __init__(self): if not hasattr(self, 'initialized'): self.connection = self.connect() self.initialized = True def connect(self): print("Connecting to database...") return "DB Connection" # 使用示例 db1 = DatabaseConnection() db2 = DatabaseConnection() print(db1 is db2) # True — 同一个实例! ``` ### JavaScript 实现 ```javascript class DatabaseConnection { constructor() { if (DatabaseConnection.instance) { return DatabaseConnection.instance; } this.connection = this.connect(); DatabaseConnection.instance = this; } connect() { console.log("Connecting to database..."); return "DB Connection"; } } // 使用示例 const db1 = new DatabaseConnection(); const db2 = new DatabaseConnection(); console.log(db1 === db2); // true ``` ### 何时使用 - **适用**:日志记录器、配置管理、连接池、缓存 - **不适用**:当你需要多个实例时,或用于简单工具类(改用模块) ### 优缺点 ✅ 对唯一实例的受控访问 ✅ 延迟初始化(Lazy initialization) ❌ 全局状态(可能增加测试难度) ❌ 可能违反单一职责原则(Single Responsibility Principle) --- ## 2. 工厂模式(Factory Pattern) ### 问题 你需要在未指定具体类的情况下创建对象。创建逻辑复杂或依赖于条件。 ### 反面示例 ```python # 客户端代码需要了解所有具体类 class Dog: def speak(self): return "Woof!" class Cat: def speak(self): return "Meow!" # 客户端必须知道实例化哪个类 def get_pet(pet_type): if pet_type == "dog": return Dog() elif pet_type == "cat": return Cat() # 添加新宠物类型需要修改此函数! ``` ### 解决方案 ```python from abc import ABC, abstractmethod # 抽象产品 class Animal(ABC): @abstractmethod def speak(self): pass # 具体产品 class Dog(Animal): def speak(self): return "Woof!" class Cat(Animal): def speak(self): return "Meow!" class Bird(Animal): def speak(self): return "Tweet!" # 工厂 class AnimalFactory: @staticmethod def create_animal(animal_type): animals = { 'dog': Dog, 'cat': Cat, 'bird': Bird } animal_class = animals.get(animal_type.lower()) if animal_class: return animal_class() raise ValueError(f"Unknown animal type: {animal_type}") # 使用示例 factory = AnimalFactory() pet = factory.create_animal('dog') print(pet.speak()) # Woof! ``` ### JavaScript 实现 ```javascript class Animal { speak() { throw new Error("Method must be implemented"); } } class Dog extends Animal { speak() { return "Woof!"; } } class Cat extends Animal { speak() { return "Meow!"; } } class AnimalFactory { static createAnimal(animalType) { const animals = { dog: Dog, cat: Cat }; const AnimalClass = animals[animalType.toLowerCase()]; if (AnimalClass) { return new AnimalClass(); } throw new Error(`Unknown animal type: ${animalType}`); } } // 使用示例 const pet = AnimalFactory.createAnimal('dog'); console.log(pet.speak()); // Woof! ``` ### 何时使用 - **适用**:当你事先不知道确切类型时,或创建逻辑较为复杂 - **不适用**:用于没有变化的简单对象创建 ### 优缺点 ✅ 客户端与产品之间的松耦合 ✅ 易于添加新产品(开闭原则,Open/Closed Principle) ✅ 集中化的创建逻辑 ❌ 可能引入大量类 --- ## 3. 抽象工厂模式(Abstract Factory Pattern) ### 问题 你需要在未指定具体类的情况下创建一组相关的对象家族。 ### 示例:UI 主题工厂 ```python from abc import ABC, abstractmethod # 抽象产品 class Button(ABC): @abstractmethod def render(self): pass class Checkbox(ABC): @abstractmethod def render(self): pass # 具体产品 —— 浅色主题 class LightButton(Button): def render(self): return "Rendering light button" class LightCheckbox(Checkbox): def render(self): return "Rendering light checkbox" # 具体产品 —— 深色主题 class DarkButton(Button): def render(self): return "Rendering dark button" class DarkCheckbox(Checkbox): def render(self): return "Rendering dark checkbox" # 抽象工厂 class UIFactory(ABC): @abstractmethod def create_button(self): pass @abstractmethod def create_checkbox(self): pass # 具体工厂 class LightThemeFactory(UIFactory): def create_button(self): return LightButton() def create_checkbox(self): return LightCheckbox() class DarkThemeFactory(UIFactory): def create_button(self): return DarkButton() def create_checkbox(self): return DarkCheckbox() # 客户端代码 def create_ui(factory: UIFactory): button = factory.create_button() checkbox = factory.create_checkbox() return button.render(), checkbox.render() # 使用示例 light_factory = LightThemeFactory() print(create_ui(light_factory)) dark_factory = DarkThemeFactory() print(create_ui(dark_factory)) ``` ### 何时使用 - **适用**:当你需要一组相关的对象协同工作时 - **不适用**:当你只有一个产品家族时 --- ## 4. 构建器模式(Builder Pattern) ### 问题 你需要逐步构建复杂对象。构造函数参数过多。 ### 反面示例 ```python # 构造函数参数过多 class Pizza: def __init__(self, size, cheese=False, pepperoni=False, mushrooms=False, onions=False, bacon=False, ham=False, pineapple=False): self.size = size self.cheese = cheese self.pepperoni = pepperoni # ... 大量参数 # 难以阅读,容易出错 pizza = Pizza(12, True, True, False, True, False, True, False) ``` ### 解决方案 ```python class Pizza: def __init__(self, size): self.size = size self.cheese = False self.pepperoni = False self.mushrooms = False self.onions = False self.bacon = False def __str__(self): toppings = [] if self.cheese: toppings.append("cheese") if self.pepperoni: toppings.append("pepperoni") if self.mushrooms: toppings.append("mushrooms") if self.onions: toppings.append("onions") if self.bacon: toppings.append("bacon") return f"{self.size}\" pizza with {', '.join(toppings)}" class PizzaBuilder: def __init__(self, size): self.pizza = Pizza(size) def add_cheese(self): self.pizza.cheese = True return self def add_pepperoni(self): self.pizza.pepperoni = True return self def add_mushrooms(self): self.pizza.mushrooms = True return self def add_onions(self): self.pizza.onions = True return self def add_bacon(self): self.pizza.bacon = True return self def build(self): return self.pizza # 使用示例 —— 可读性大大提升! pizza = (PizzaBuilder(12) .add_cheese() .add_pepperoni() .add_mushrooms() .build()) print(pizza) # 12" pizza with cheese, pepperoni, mushrooms ``` ### JavaScript 实现 ```javascript class Pizza { constructor(size) { this.size = size; this.toppings = []; } toString() { return `${this.size}" pizza with ${this.toppings.join(', ')}`; } } class PizzaBuilder { constructor(size) { this.pizza = new Pizza(size); } addCheese() { this.pizza.toppings.push('cheese'); return this; } addPepperoni() { this.pizza.toppings.push('pepperoni'); return this; } addMushrooms() { this.pizza.toppings.push('mushrooms'); return this; } build() { return this.pizza; } } // 使用示例 const pizza = new PizzaBuilder(12) .addCheese() .addPepperoni() .addMushrooms() .build(); console.log(pizza.toString()); ``` ### 何时使用 - **适用**:构造函数参数多、需要逐步构建、需要不可变对象 - **不适用**:参数少的简单对象 ### 优缺点 ✅ 可读性强的流畅接口(Fluent Interface) ✅ 对构建过程的精细控制 ✅ 可以创建不同的表示形式 ❌ 代码量增加(需要构建器类) --- ## 5. 原型模式(Prototype Pattern) ### 问题 你需要复制现有对象,而不让代码依赖于它们的类。 ### 解决方案 ```python import copy class Prototype: def clone(self): """对象的深拷贝。""" return copy.deepcopy(self) class Shape(Prototype): def __init__(self, shape_type, color): self.shape_type = shape_type self.color = color self.coordinates = [] def __str__(self): return f"{self.color} {self.shape_type} at {self.coordinates}" # 使用示例 original = Shape("Circle", "Red") original.coordinates = [10, 20] # 克隆 clone = original.clone() clone.color = "Blue" clone.coordinates = [30, 40] print(original) # Red Circle at [10, 20] print(clone) # Blue Circle at [30, 40] ``` ### JavaScript 实现 ```javascript class Shape { constructor(shapeType, color) { this.shapeType = shapeType; this.color = color; this.coordinates = []; } clone() { const cloned = Object.create(Object.getPrototypeOf(this)); cloned.shapeType = this.shapeType; cloned.color = this.color; cloned.coordinates = [...this.coordinates]; return cloned; } toString() { return `${this.color} ${this.shapeType} at ${this.coordinates}`; } } // 使用示例 const original = new Shape("Circle", "Red"); original.coordinates = [10, 20]; const clone = original.clone(); clone.color = "Blue"; clone.coordinates = [30, 40]; console.log(original.toString()); // Red Circle at 10,20 console.log(clone.toString()); // Blue Circle at 30,40 ``` ### 何时使用 - **适用**:对象创建成本高,需要大量相似对象 - **不适用**:简单对象,浅拷贝即可满足需求 --- ## 模式选择指南 | 模式 | 适用场景 | 典型用例 | |---------|----------|-------------------| | **单例模式(Singleton)** | 需要唯一实例 | 日志记录器、配置管理、数据库连接池 | | **工厂模式(Factory)** | 编译时不知道具体类 | 插件系统、文档类型 | | **抽象工厂模式(Abstract Factory)** | 需要一组相关的对象 | UI 主题、跨平台应用 | | **构建器模式(Builder)** | 参数众多的复杂构建过程 | 查询构建器、文档构建器 | | **原型模式(Prototype)** | 创建成本高,需要副本 | 游戏实体、图形编辑器 | --- ## 应避免的反模式 ### 1. 过度使用单例 ```python # 不要把所有东西都做成单例 class MathUtils(Singleton): # 糟糕 —— 直接使用模块即可! @staticmethod def add(a, b): return a + b # 应使用模块级函数 def add(a, b): return a + b ``` ### 2. 上帝工厂 ```python # 不要用一个工厂处理所有事情 class GodFactory: def create_user(self): ... def create_product(self): ... def create_order(self): ... # ... 还有 50 多个方法 # 应按不同关注点使用独立的工厂 class UserFactory: ... class ProductFactory: ... class OrderFactory: ... ``` ### 3. 过早抽象 ```python # 不要在简单情况下创建工厂 class DogFactory: @staticmethod def create(): return Dog() # 只有一个简单的类 # 应直接实例化 dog = Dog() ``` --- ## 关键要点 1. **单例模式**:唯一实例,全局访问 2. **工厂模式**:将对象创建与使用解耦 3. **抽象工厂模式**:一组相关的对象家族 4. **构建器模式**:逐步构建复杂对象 5. **原型模式**:克隆现有对象 **请记住**:在模式确实能解决实际问题时再使用。不要在模式不适用时强行套用!