模式对比与选择
High Contrast
Dark Mode
Light Mode
Sepia
Forest
6 min read1,173 words

模式对比与选择

学习设计模式后,你可能会面临"何时使用哪个模式"的困惑。本章将对比相似的设计模式,帮助你做出正确的选择。

相似模式对比

创建型模式对比

模式 目的 何时使用
单例模式 确保唯一实例 需要全局唯一的资源(数据库连接池、配置管理器)
工厂方法 创建对象 不知道具体类型,需要延迟创建
抽象工厂 创建产品族 需要创建相关的对象族(不同UI组件)
建造者 构建复杂对象 对象有很多参数,需要分步骤构建
graph TB A[创建型模式] --> B[单例] A --> C[工厂方法] A --> D[抽象工厂] A --> E[建造者] B --> B1[唯一实例] B --> B1[全局访问] C --> C1[单一产品] C --> C2[延迟创建] D --> D1[产品族] D --> D2[相关对象] E --> E1[复杂对象] E --> E2[分步骤构建] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px

工厂方法 vs 抽象工厂

# 工厂方法 - 创建单一产品
class PizzaFactory:
def create_pizza(self, pizza_type):
if pizza_type == "cheese":
return CheesePizza()
elif pizza_type == "pepperoni":
return PepperoniPizza()
# 抽象工厂 - 创建产品族
class UIFactory:
def create_button(self):
pass
def create_checkbox(self):
pass
class WindowsFactory(UIFactory):
def create_button(self):
return WindowsButton()
def create_checkbox(self):
return WindowsCheckbox()
class MacFactory(UIFactory):
def create_button(self):
return MacButton()
def create_checkbox(self):
return MacCheckbox()

选择标准: - 需要创建一种产品的多种类型 → 工厂方法 - 需要创建多个相关的产品 → 抽象工厂

结构型模式对比

模式 目的 何时使用
适配器 转换接口 集成不兼容的第三方API
装饰器 添加功能 动态添加/删除功能
代理 控制访问 延迟加载、权限控制、缓存
外观 简化接口 简化复杂子系统
组合 树形结构 表达部分-整体层次
graph TB A[结构型模式] --> B[适配器] A --> C[装饰器] A --> D[代理] A --> E[外观] A --> F[组合] B --> B1[接口转换] C --> C1[动态添加功能] D --> D1[控制访问] E --> E1[简化接口] F --> F1[树形结构] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px

适配器 vs 装饰器 vs 代理

# 适配器 - 转换接口
class ThirdPartyAPI:
def old_method(self, data):
print(f"旧接口: {data}")
class NewInterfaceAdapter:
def __init__(self, api):
self.api = api
def new_method(self, data):
# 转换接口
self.api.old_method(data)
# 装饰器 - 添加功能
class LoggerDecorator:
def __init__(self, component):
self.component = component
def operation(self):
print("日志: 开始操作")
result = self.component.operation()
print("日志: 操作完成")
return result
# 代理 - 控制访问
class DatabaseProxy:
def __init__(self, real_db):
self.real_db = real_db
self.cache = {}
def query(self, sql):
if sql in self.cache:
return self.cache[sql]
result = self.real_db.query(sql)
self.cache[sql] = result
return result

选择标准: - 接口不兼容 → 适配器 - 需要动态添加功能 → 装饰器 - 需要控制访问/延迟加载/缓存 → 代理

行为型模式对比

模式 目的 何时使用
观察者 一对多通知 事件驱动、发布订阅
策略 算法可互换 多种算法可替换
模板方法 算法骨架 算法结构相同,部分步骤不同
命令 封装请求 需要撤销、队列、延迟执行
迭代器 遍历集合 需要统一遍历方式
状态 随状态改变行为 对象行为随状态改变
graph TB A[行为型模式] --> B[观察者] A --> C[策略] A --> D[模板方法] A --> E[命令] A --> F[迭代器] A --> G[状态] B --> B1[一对多通知] C --> C1[算法可互换] D --> D1[算法骨架] E --> E1[封装请求] F --> F1[遍历集合] G --> G1[随状态改变] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px

策略模式 vs 状态模式

# 策略模式 - 算法可互换
class SortStrategy:
def sort(self, data):
pass
class BubbleSort(SortStrategy):
def sort(self, data):
print("冒泡排序")
class QuickSort(SortStrategy):
def sort(self, data):
print("快速排序")
class Sorter:
def __init__(self, strategy):
self.strategy = strategy
def sort(self, data):
self.strategy.sort(data)  # 策略可手动切换
# 状态模式 - 随状态改变行为
class OrderState:
def confirm(self):
pass
class PendingState(OrderState):
def confirm(self):
print("订单已确认")
return ConfirmedState()
class ConfirmedState(OrderState):
def confirm(self):
print("订单已确认")
return self
class Order:
def __init__(self):
self.state = PendingState()
def confirm(self):
self.state = self.state.confirm()  # 状态自动转换

选择标准: - 算法可手动选择和替换 → 策略模式 - 行为随状态自动改变 → 状态模式

实际场景选择指南

场景1:需要创建对象

graph LR A[需要创建对象] --> B{对象数量} B -->|1个| C{需要唯一实例?} B -->|多个| D{对象类型?} C -->|是| E[单例模式] C -->|否| F{对象复杂?} F -->|是| G[建造者模式] F -->|否| H[工厂方法模式] D -->|1种类型| H D -->|相关对象族| I[抽象工厂模式] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px style E fill:#e3f2fd,stroke:#1976d2,stroke-width:2px style G fill:#e3f2fd,stroke:#1976d2,stroke-width:2px style H fill:#e3f2fd,stroke:#1976d2,stroke-width:2px style I fill:#e3f2fd,stroke:#1976d2,stroke-width:2px

场景2:需要扩展功能

graph LR A[需要扩展功能] --> B{如何扩展} B -->|接口不兼容| C[适配器模式] B -->|添加功能| D{是否动态?} D -->|是| E[装饰器模式] D -->|否| F[继承] B -->|控制访问| G[代理模式] B -->|简化接口| H[外观模式] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px style C fill:#fff9c4,stroke:#f9a825,stroke-width:2px style E fill:#fff9c4,stroke:#f9a825,stroke-width:2px style G fill:#fff9c4,stroke:#f9a825,stroke-width:2px style H fill:#fff9c4,stroke:#f9a825,stroke-width:2px

场景3:需要处理行为

graph LR A[需要处理行为] --> B{需求} B -->|通知多个对象| C[观察者模式] B -->|算法可互换| D[策略模式] B -->|算法骨架固定| E[模板方法模式] B -->|封装请求| F[命令模式] B -->|遍历集合| G[迭代器模式] B -->|随状态改变| H[状态模式] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px style C fill:#c8e6c9,stroke:#43a047,stroke-width:2px style D fill:#c8e6c9,stroke:#43a047,stroke-width:2px style E fill:#c8e6c9,stroke:#43a047,stroke-width:2px style F fill:#c8e6c9,stroke:#43a047,stroke-width:2px style G fill:#c8e6c9,stroke:#43a047,stroke-width:2px style H fill:#c8e6c9,stroke:#43a047,stroke-width:2px

组合使用多个模式

实际项目中,多个模式经常组合使用。

示例:电商系统

# 组合使用多个模式
class PaymentSystem:
def __init__(self):
# 单例模式 - 配置管理器
self.config = ConfigManager.getInstance()
# 工厂方法 - 创建支付方式
self.factory = PaymentFactory()
# 策略模式 - 支付策略
self.payment_strategy = None
# 观察者模式 - 支付通知
self.observers = []
# 模板方法 - 支付流程
def process_payment(self, payment_type, amount):
self.validate_payment()
self.execute_payment(payment_type, amount)
self.notify_observers()
# 装饰器模式 - 添加日志
def process_payment(self, payment_type, amount):
self._log_start()
# 原有逻辑
self._log_end()
# 组合关系说明:
# 1. 单例模式:配置管理器全局唯一
# 2. 工厂方法:创建不同支付方式
# 3. 策略模式:支付算法可替换
# 4. 观察者模式:支付完成后通知
# 5. 模板方法:支付流程骨架
# 6. 装饰器模式:添加日志功能

反模式与常见错误

❌ 错误1:过度设计

# 简单的加法也用模式?
class AddCommand:
def execute(self):
return self.x + self.y
class Calculator:
def add(self, x, y):
command = AddCommand(x, y)
return command.execute()
# ❌ 太复杂了!应该直接:
def add(x, y):
return x + y

❌ 错误2:模式滥用

# 为了用模式而用模式
class SingleCalculator:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def add(self, x, y):
return x + y
# 计算器不需要单例!用普通类或静态方法即可

❌ 错误3:忽略语言特性

# Python的@property比模式更简单
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@property
def area(self):
return 3.14 * self._radius ** 2
# 不需要代理模式

选择设计模式的步骤

第1步:识别问题

  1. 创建问题 - 需要创建对象吗?
  2. 结构问题 - 需要组合对象吗?
  3. 行为问题 - 需要处理交互吗?

第2步:分析需求

问题 关键词 推荐模式
创建对象 唯一、工厂、构建 单例、工厂方法、建造者
接口兼容 不兼容、转换 适配器
功能扩展 动态、添加 装饰器
访问控制 延迟、缓存、权限 代理
简化接口 复杂、子系统 外观
树形结构 部分-整体、层次 组合
算法切换 可互换、算法 策略
算法骨架 固定步骤、部分不同 模板方法
一对多通知 订阅、事件 观察者
封装请求 撤销、队列 命令
遍历集合 统一方式 迭代器
状态改变 状态相关行为 状态

第3步:考虑语言特性

Python有许多特性可以简化模式实现:

模式 Python简化方式
单例 模块变量、类装饰器
工厂方法 简单工厂、@classmethod
适配器 鸭子类型
装饰器 @decorator语法
迭代器 生成器
策略 函数作为参数

第4步:评估复杂度

graph LR A[问题复杂度] --> B{复杂?} B -->|否| C[简单实现] B -->|是| D{是否经常变化?} D -->|否| E[考虑模式] D -->|是| F[强烈建议模式] style A fill:#ede7f6,stroke:#5e35b1,stroke-width:3px style C fill:#ffcdd2,stroke:#c62828,stroke-width:2px style E fill:#fff9c4,stroke:#f9a825,stroke-width:2px style F fill:#c8e6c9,stroke:#43a047,stroke-width:2px

模式选择清单

在选择模式前,问自己以下问题:

✅ 需要模式的情况

❌ 不需要模式的情况

本章要点


下一步实际项目案例 🚀