创建型模式关注对象的创建机制,将对象的实例化过程与使用过程解耦,提高代码的灵活性和复用性。


1. 单例模式(Singleton)

意图

确保一个类只有一个实例,并提供一个全局访问点

问题

某些类(如配置管理器、日志记录器)只需一个实例。如果存在多个实例,会导致状态不一致或资源浪费。

解决方案

  • 将构造函数私有化(语言支持时),使外界无法直接创建实例。
  • 类内部维护一个静态私有成员变量,保存唯一实例。
  • 提供一个静态公有方法(如 getInstance())返回该实例。
  • 第一次调用时创建实例,后续直接返回已有实例(懒加载)。

结构(UML)

┌─────────────────┐
│   Singleton     │
├─────────────────┤
│ - instance      │  (静态私有)
├─────────────────┤
│ + getInstance() │
│ - Singleton()   │
└─────────────────┘

参与者

  • Singleton:定义 getInstance 方法,负责创建和管理自己的唯一实例。

协作

  • 客户端通过 Singleton.getInstance() 获取实例,而不是直接 new Singleton()

适用性

  • 类只能有一个实例,且客户端需要从全局单一访问点访问它。
  • 该唯一实例需要通过子类化扩展,且客户端无需修改代码即可使用扩展实例。

Python 示例

# 模块级单例(利用 Python 模块的天然单例特性)
class Singleton:
    def __init__(self):
        self.value = 0
 
_instance = Singleton()
 
def get_instance():
    return _instance
 
# 使用
s1 = get_instance()
s2 = get_instance()
assert s1 is s2

2. 工厂方法模式(Factory Method)

意图

定义一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法将实例化延迟到子类。

问题

一个类需要创建对象,但具体类型在编译时无法确定,或者需要将创建逻辑与使用逻辑解耦。

解决方案

  • Creator 类声明一个抽象工厂方法,返回产品类型。
  • ConcreteCreator 子类实现该工厂方法,返回具体产品实例。
  • 客户端依赖产品接口和创建者接口,无需知道具体产品类名。

结构(UML)

┌─────────────┐          ┌─────────────┐
│   Product   │          │   Creator   │
├─────────────┤          ├─────────────┤
│ + operation │          │ + factoryMethod() │
└─────────────┘          │ + someOperation() │
        △                └─────────────┘
        │                         △
┌─────────────┐          ┌─────────────┐
│ ConcreteProduct│        │ ConcreteCreator│
├─────────────┤          ├─────────────┤
│ + operation │          │ + factoryMethod() │
└─────────────┘          └─────────────┘

参与者

  • Product:定义产品对象的公共接口。
  • ConcreteProduct:实现 Product 接口的具体产品类。
  • Creator:声明工厂方法,通常还包含调用工厂方法的核心业务逻辑。
  • ConcreteCreator:实现工厂方法,返回具体产品实例。

协作

  • 客户端调用 Creator 的 someOperation(),后者调用工厂方法创建产品,然后使用产品。
  • 不同 ConcreteCreator 返回不同 ConcreteProduct,从而改变行为。

适用性

  • 一个类无法预知它必须创建的对象类型。
  • 类希望其子类决定创建什么对象。
  • 将创建逻辑与使用逻辑分离,符合开闭原则。

Python 示例

from abc import ABC, abstractmethod
 
# Product
class Animal(ABC):
    @abstractmethod
    def speak(self): pass
 
# Concrete Products
class Dog(Animal):
    def speak(self): return "Woof"
 
class Cat(Animal):
    def speak(self): return "Meow"
 
# Creator
class AnimalFactory(ABC):
    @abstractmethod
    def create_animal(self) -> Animal: pass
 
    def make_sound(self):
        animal = self.create_animal()
        print(animal.speak())
 
# Concrete Creators
class DogFactory(AnimalFactory):
    def create_animal(self) -> Animal: return Dog()
 
class CatFactory(AnimalFactory):
    def create_animal(self) -> Animal: return Cat()
 
# Client
def client_code(factory: AnimalFactory):
    factory.make_sound()
 
client_code(DogFactory())  # Woof
client_code(CatFactory())  # Meow

3. 抽象工厂模式(Abstract Factory)

意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

问题

需要创建一组产品(如 UI 组件:按钮、复选框),它们有多种风格(如 Windows、Mac)。客户端不应依赖具体类。

解决方案

  • 声明抽象工厂接口,其中包含每个产品类型的创建方法(如 createButton, createCheckbox)。
  • 为每种产品族(如 Windows 风格)实现具体工厂类,每个工厂负责创建该族所有产品。
  • 客户端接收抽象工厂接口,运行时注入具体工厂,从而创建整个产品族。

结构(UML)

          ┌─────────────────┐
          │ AbstractFactory │
          ├─────────────────┤
          │ + createButton()│
          │ + createCheckbox()│
          └─────────────────┘
                    △
         ┌──────────┴──────────┐
   ┌─────────────┐       ┌─────────────┐
   │ WinFactory  │       │ MacFactory  │
   ├─────────────┤       ├─────────────┤
   │ + createButton() │   │ + createButton() │
   │ + createCheckbox()│   │ + createCheckbox()│
   └─────────────┘       └─────────────┘

参与者

  • AbstractFactory:声明创建抽象产品对象的操作。
  • ConcreteFactory:实现创建具体产品对象的操作。
  • AbstractProduct:为一种产品类型声明接口。
  • ConcreteProduct:定义被具体工厂创建的产品对象。
  • Client:仅使用 AbstractFactory 和 AbstractProduct 接口。

协作

  • 客户端创建具体工厂对象,然后通过该工厂创建所需产品。
  • 产品系列通过同一个工厂保持一致(例如 Windows 工厂创建的所有控件都是 Windows 风格)。

适用性

  • 系统独立于产品的创建、组合和表示。
  • 系统需要配置多个产品系列之一。
  • 强制相关产品对象一起使用。

Python 示例

from abc import ABC, abstractmethod
 
# Abstract Products
class Button(ABC):
    @abstractmethod
    def paint(self): pass
 
class Checkbox(ABC):
    @abstractmethod
    def paint(self): pass
 
# Concrete Products for Windows
class WinButton(Button):
    def paint(self): print("Windows button")
 
class WinCheckbox(Checkbox):
    def paint(self): print("Windows checkbox")
 
# Concrete Products for Mac
class MacButton(Button):
    def paint(self): print("Mac button")
 
class MacCheckbox(Checkbox):
    def paint(self): print("Mac checkbox")
 
# Abstract Factory
class GUIFactory(ABC):
    @abstractmethod
    def create_button(self) -> Button: pass
    @abstractmethod
    def create_checkbox(self) -> Checkbox: pass
 
# Concrete Factories
class WinFactory(GUIFactory):
    def create_button(self) -> Button: return WinButton()
    def create_checkbox(self) -> Checkbox: return WinCheckbox()
 
class MacFactory(GUIFactory):
    def create_button(self) -> Button: return MacButton()
    def create_checkbox(self) -> Checkbox: return MacCheckbox()
 
# Client
def render_ui(factory: GUIFactory):
    btn = factory.create_button()
    chk = factory.create_checkbox()
    btn.paint()
    chk.paint()
 
# 根据平台选择工厂
import sys
factory = WinFactory() if sys.platform == "win32" else MacFactory()
render_ui(factory)

4. 建造者模式(Builder)

意图

将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

问题

创建一个由多个部分组成的复杂对象(如文档、计算机),构造过程应独立于这些部分的装配方式。

解决方案

  • Builder 接口声明构建产品各部分的方法。
  • ConcreteBuilder 实现这些方法,并提供一个返回最终产品的方法。
  • Director 负责按照特定顺序调用 Builder 的方法来构建产品。
  • 客户端通过 Director 与 Builder 交互,不直接接触产品构造细节。

结构(UML)

┌─────────────┐      ┌─────────────┐
│  Director   │      │   Builder   │
├─────────────┤      ├─────────────┤
│ + construct()│─────▶│ + buildPartA()│
└─────────────┘      │ + buildPartB()│
                     │ + getResult() │
                     └─────────────┘
                            △
                     ┌─────────────┐
                     │ConcreteBuilder│
                     ├─────────────┤
                     │ + buildPartA()│
                     │ + buildPartB()│
                     │ + getResult() │
                     └─────────────┘

参与者

  • Builder:为创建产品各个部分声明接口。
  • ConcreteBuilder:实现 Builder 接口,构造并装配产品各部分,提供获取产品的接口。
  • Director:构造一个使用 Builder 接口的对象,定义构建产品的步骤。
  • Product:表示被构造的复杂对象,通常包含多个部分。

协作

  • 客户端创建 Director 和 ConcreteBuilder,将 Builder 交给 Director。
  • Director 调用 Builder 的方法构建产品,客户端从 Builder 获取最终产品。

适用性

  • 创建复杂对象的算法应独立于该对象的组成部分及其装配方式。
  • 构造过程允许被构造的对象有不同的表示。

Python 示例

# Product
class Computer:
    def __init__(self):
        self.cpu = None
        self.ram = None
        self.storage = None
 
    def __str__(self):
        return f"Computer(cpu={self.cpu}, ram={self.ram}, storage={self.storage})"
 
# Builder
class ComputerBuilder:
    def __init__(self):
        self.computer = Computer()
    def set_cpu(self, cpu): self.computer.cpu = cpu; return self
    def set_ram(self, ram): self.computer.ram = ram; return self
    def set_storage(self, storage): self.computer.storage = storage; return self
    def build(self): return self.computer
 
# Director
class Director:
    def __init__(self, builder: ComputerBuilder):
        self._builder = builder
    def build_gaming_computer(self):
        return self._builder.set_cpu("Intel i9").set_ram("32GB").set_storage("1TB SSD").build()
    def build_office_computer(self):
        return self._builder.set_cpu("Intel i5").set_ram("16GB").set_storage("512GB SSD").build()
 
# Client
builder = ComputerBuilder()
director = Director(builder)
gaming_pc = director.build_gaming_computer()
office_pc = director.build_office_computer()
print(gaming_pc)
print(office_pc)

5. 原型模式(Prototype)

意图

原型实例指定创建对象的种类,并通过复制这个原型创建新的对象。

问题

创建对象成本较高(如数据库查询、复杂计算),或者需要避免子类化。

解决方案

  • 提供一个克隆接口(如 clone() 方法),允许对象复制自身。
  • 客户端通过复制原型对象来创建新对象,而不是调用构造函数。

结构(UML)

┌─────────────┐
│  Prototype  │
├─────────────┤
│ + clone()   │
└─────────────┘
        △
┌─────────────┐
│ConcretePrototype│
├─────────────┤
│ + clone()   │
└─────────────┘

参与者

  • Prototype:声明克隆自身的接口。
  • ConcretePrototype:实现克隆方法,复制自身的数据。
  • Client:通过克隆原型创建新对象。

协作

  • 客户端请求原型对象克隆自身,得到一个新实例,该实例与原型独立但内容相同。

适用性

  • 系统应独立于产品的创建、组合和表示。
  • 实例化类在运行时指定(如动态加载)。
  • 避免创建与产品类层次平行的工厂类层次。
  • 类的实例只有少数几种状态组合。

Python 示例

import copy
 
# Prototype
class Prototype:
    def clone(self):
        return copy.deepcopy(self)
 
# Concrete Prototype
class Document(Prototype):
    def __init__(self, title, content, metadata):
        self.title = title
        self.content = content
        self.metadata = metadata   # 例如字典,需要深拷贝
 
    def __str__(self):
        return f"Document(title={self.title}, content={self.content[:10]}..., metadata={self.metadata})"
 
# Client
original = Document("Report", "This is the content...", {"author": "Alice", "version": 1})
cloned = original.clone()
cloned.title = "Report Copy"
cloned.metadata["version"] = 2
 
print(original)
print(cloned)
# 修改克隆不影响原对象(深拷贝)

创建型模式总结

模式核心思想解决的主要问题
单例唯一实例 + 全局访问点确保一个类只有一个实例
工厂方法定义创建接口,子类决定具体类型将对象的创建延迟到子类
抽象工厂创建一系列相关产品族产品族的替换与统一创建
建造者分步构建复杂对象,同一过程多种表示复杂对象的构造与表示分离
原型通过复制原型创建新对象避免昂贵构造或重复初始化