下面我将全面解析18种Python设计模式,每种模式都包含实际应用场景、优缺点分析、框架引用案例、可运行代码示例以及正反案例对比,帮助您深入理解设计模式的价值。
一、创建型模式(5种)
1. 单例模式(Singleton)
场景:数据库连接池、全局配置管理
优点:资源复用,保证全局一致性
缺点:违反单一职责,多线程需同步
框架应用:Django配置对象 django.conf.settings
class DatabaseConnection:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
# 模拟数据库连接初始化
print("创建新的数据库连接(昂贵操作)")
return cls._instance
# 正面示例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True,复用同一连接
# 反面示例(无单例)
class BadDatabase:
def __init__(self):
print("创建新的数据库连接(昂贵操作)")
db3 = BadDatabase()
db4 = BadDatabase() # 重复创建连接,浪费资源
2. 工厂方法模式(Factory Method)
场景:支付网关切换、日志处理器选择
优点:解耦客户端和具体类
缺点:增加代码复杂度
from abc import ABC, abstractmethod
class PaymentGateway(ABC):
@abstractmethod
def pay(self, amount): pass
class StripeGateway(PaymentGateway):
def pay(self, amount):
print(f"Stripe支付 ${amount}")
class PayPalGateway(PaymentGateway):
def pay(self, amount):
print(f"PayPal支付 ${amount}")
def payment_factory(gateway_type):
if gateway_type == "stripe": return StripeGateway()
if gateway_type == "paypal": return PayPalGateway()
raise ValueError("无效支付网关")
# 正面示例
payment = payment_factory("stripe")
payment.pay(100) # 客户端无需知道具体实现类
# 反面示例(硬编码依赖)
class OrderProcessor:
def process_payment(self, amount):
gateway = StripeGateway() # 直接依赖具体类
gateway.pay(amount)
# 更换支付网关需修改源码
3. 抽象工厂模式(Abstract Factory)
场景:跨平台UI组件库
优点:确保产品兼容性
缺点:扩展新产品困难
class Button(ABC):
@abstractmethod
def render(self): pass
class WindowsButton(Button):
def render(self): print("Windows风格按钮")
class MacButton(Button):
def render(self): print("Mac风格按钮")
class GUIFactory(ABC):
@abstractmethod
def create_button(self): pass
class WindowsFactory(GUIFactory):
def create_button(self): return WindowsButton()
class MacFactory(GUIFactory):
def create_button(self): return MacButton()
# 正面示例
def create_ui(os_type):
factory = WindowsFactory() if os_type == "windows" else MacFactory()
button = factory.create_button()
button.render() # 自动匹配操作系统风格
# 反面示例(平台相关代码分散)
if os_type == "windows":
button = WindowsButton()
elif os_type == "mac":
button = MacButton()
button.render()
# 添加新平台需修改多处条件判断
4. 建造者模式(Builder)
场景:复杂对象创建(如SQL查询)
优点:分离构造过程与表示
缺点:增加额外Builder类
class SQLQuery:
def __init__(self):
self.table = ""
self.fields = []
self.where_clauses = []
def execute(self):
fields = ", ".join(self.fields) or "*"
where = (" WHERE " + " AND ".join(self.where_clauses)) if self.where_clauses else ""
print(f"SELECT {fields} FROM {self.table}{where}")
class QueryBuilder:
def __init__(self):
self.query = SQLQuery()
def select(self, *fields):
self.query.fields = fields
return self
def from_table(self, table):
self.query.table = table
return self
def where(self, condition):
self.query.where_clauses.append(condition)
return self
def build(self):
return self.query
# 正面示例
query = (QueryBuilder()
.select("id", "name")
.from_table("users")
.where("age > 18")
.build())
query.execute()
# 反面示例(构造参数爆炸)
class BadQuery:
def __init__(self, table, fields=None, where=None, joins=None, group_by=None):
# 参数过多难以维护
self.table = table
self.fields = fields or []
self.where = where or []
# ...更多参数
5. 原型模式(Prototype)
场景:游戏对象克隆、配置模板
优点:避免重复初始化开销
缺点:深拷贝可能复杂
import copy
class NPC:
def __init__(self, name, health, position):
self.name = name
self.health = health
self.position = position
# 模拟昂贵初始化
print(f"创建NPC {name}(耗时操作)")
def clone(self):
return copy.deepcopy(self)
# 正面示例
orc_template = NPC("兽人", 100, (0, 0))
orc1 = orc_template.clone() # 快速克隆
orc1.position = (10, 5)
# 反面示例(重复初始化)
orc2 = NPC("兽人", 100, (0, 0)) # 重复执行昂贵初始化
二、结构型模式(6种)
6. 适配器模式(Adapter)
场景:整合第三方库、旧系统接口改造
优点:解决接口不兼容问题
缺点:增加额外层
class LegacyLogger:
def log_message(self, msg, priority):
print(f"[{priority}] {msg}")
class ModernLogger:
def log(self, message, level="INFO"):
print(f"{level}: {message}")
class LoggerAdapter:
def __init__(self, logger):
self.logger = logger
def log(self, message, level="INFO"):
if isinstance(self.logger, LegacyLogger):
# 转换接口
priority = 1 if level == "ERROR" else 0
self.logger.log_message(message, priority)
else:
self.logger.log(message, level)
# 正面示例
legacy = LoggerAdapter(LegacyLogger())
legacy.log("系统错误", level="ERROR") # 自动转换接口
# 反面示例(直接修改第三方库)
# 修改LegacyLogger源码使其兼容ModernLogger接口 → 违反开闭原则
7. 装饰器模式(Decorator)
场景:功能扩展(日志、缓存、权限)
优点:动态添加功能,符合开闭原则
缺点:多层装饰可读性下降
框架应用:Flask路由装饰器 @app.route
def log_execution(func):
def wrapper(*args, **kwargs):
print(f"执行: {func.__name__}")
return func(*args, **kwargs)
return wrapper
def cache_result(func):
cache = {}
def wrapper(*args):
if args in cache:
print("返回缓存结果")
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
@log_execution
@cache_result
def fibonacci(n):
if n <= 1: return n
return fibonacci(n-1) + fibonacci(n-2)
# 正面示例
print(fibonacci(10)) # 带日志和缓存
# 反面示例(硬编码功能)
def bad_fibonacci(n):
print(f"执行: bad_fibonacci") # 日志硬编码
# ...实现+缓存逻辑混合...
8. 代理模式(Proxy)
场景:延迟加载、访问控制
优点:控制对象访问,实现懒加载
缺点:增加响应时间
class HighResImage:
def __init__(self, filename):
self.filename = filename
self._load_image()
def _load_image(self):
print(f"加载高清图片: {self.filename}(耗时操作)")
def display(self):
print(f"显示: {self.filename}")
class ImageProxy:
def __init__(self, filename):
self.filename = filename
self._real_image = None
def display(self):
if not self._real_image:
self._real_image = HighResImage(self.filename)
self._real_image.display()
# 正面示例
gallery = [ImageProxy(f"image{i}.jpg") for i in range(3)]
gallery[0].display() # 仅加载第一张
# 反面示例(提前加载所有资源)
images = [HighResImage(f"image{i}.jpg") for i in range(3)] # 启动时全部加载
9. 外观模式(Facade)
场景:简化复杂子系统调用
优点:提供统一接口,降低耦合
缺点:可能成为"上帝对象"
class CPU:
def process(self): print("CPU处理数据")
class Memory:
def load(self): print("内存加载数据")
class HardDrive:
def read(self): print("硬盘读取数据")
class Computer:
def __init__(self):
self.cpu = CPU()
self.memory = Memory()
self.hd = HardDrive()
def start(self):
self.hd.read()
self.memory.load()
self.cpu.process()
# 正面示例
pc = Computer()
pc.start() # 简单调用接口
# 反面示例(客户端直接调用子系统)
hd = HardDrive()
mem = Memory()
cpu = CPU()
hd.read()
mem.load()
cpu.process() # 客户端需了解所有细节
10. 享元模式(Flyweight)
场景:文本编辑器字符格式
优点:大幅减少内存使用
缺点:增加代码复杂度
class CharacterStyle:
_cache = {}
def __new__(cls, font, size, color):
key = (font, size, color)
if key not in cls._cache:
cls._cache[key] = super().__new__(cls)
cls._cache[key].font = font
cls._cache[key].size = size
cls._cache[key].color = color
return cls._cache[key]
class Document:
def __init__(self):
self.chars = []
def add_char(self, char, font, size, color):
style = CharacterStyle(font, size, color)
self.chars.append((char, style))
def render(self):
for char, style in self.chars:
print(f"渲染 '{char}' 使用 {style.font}")
# 正面示例(1000个字符只创建2种样式)
doc = Document()
for _ in range(500):
doc.add_char('A', "Arial", 12, "black")
for _ in range(500):
doc.add_char('B', "Times", 14, "blue")
print(f"样式实例数: {len(CharacterStyle._cache)}") # 2
# 反面示例(重复创建样式)
class BadChar:
def __init__(self, char, font, size, color):
self.char = char
self.font = font
# 每个字符独立存储样式 → 内存浪费
三、行为型模式(7种)
11. 观察者模式(Observer)
场景:事件通知、消息订阅
优点:解耦发布者和订阅者
缺点:意外更新链
框架应用:Django Signals
class Newsletter:
def __init__(self):
self.subscribers = []
def subscribe(self, subscriber):
self.subscribers.append(subscriber)
def unsubscribe(self, subscriber):
self.subscribers.remove(subscriber)
def publish(self, news):
print(f"发布新闻: {news}")
for sub in self.subscribers:
sub.notify(news)
class Subscriber:
def notify(self, news):
print(f"{self.name} 收到: {news}")
class EmailSubscriber(Subscriber):
def __init__(self, name):
self.name = f"邮箱用户-{name}"
class AppSubscriber(Subscriber):
def __init__(self, name):
self.name = f"APP用户-{name}"
# 正面示例
newsletter = Newsletter()
newsletter.subscribe(EmailSubscriber("张三"))
newsletter.subscribe(AppSubscriber("李四"))
newsletter.publish("Python 3.12发布")
# 反面示例(紧耦合)
class BadNewsletter:
def publish(self, news):
print(f"发布新闻: {news}")
# 直接调用具体方法
EmailSubscriber("张三").notify(news)
AppSubscriber("李四").notify(news)
12. 策略模式(Strategy)
场景:支付方式选择、排序算法
优点:运行时切换算法
缺点:客户端需了解不同策略
class CompressionStrategy(ABC):
@abstractmethod
def compress(self, file): pass
class ZipStrategy(CompressionStrategy):
def compress(self, file):
print(f"ZIP压缩 {file}(压缩率高)")
class RarStrategy(CompressionStrategy):
def compress(self, file):
print(f"RAR压缩 {file}(加密支持)")
class Compressor:
def __init__(self, strategy=None):
self.strategy = strategy or ZipStrategy()
def set_strategy(self, strategy):
self.strategy = strategy
def compress_file(self, file):
self.strategy.compress(file)
# 正面示例
compressor = Compressor()
compressor.compress_file("data.txt")
compressor.set_strategy(RarStrategy())
compressor.compress_file("data.txt") # 动态切换算法
# 反面示例(条件分支判断)
class BadCompressor:
def compress(self, file, method="zip"):
if method == "zip":
print(f"ZIP压缩 {file}")
elif method == "rar":
print(f"RAR压缩 {file}")
# 添加新算法需修改源码
13. 模板方法模式(Template Method)
场景:算法框架定义
优点:代码复用,扩展性好
缺点:可能限制灵活性
框架应用:Django类视图 View.dispatch()
class ReportGenerator(ABC):
def generate(self):
self.collect_data()
self.process_data()
self.export()
@abstractmethod
def collect_data(self): pass
def process_data(self):
print("通用数据处理")
@abstractmethod
def export(self): pass
class PDFReport(ReportGenerator):
def collect_data(self):
print("收集PDF数据")
def export(self):
print("导出PDF文档")
class ExcelReport(ReportGenerator):
def collect_data(self):
print("收集Excel数据")
def process_data(self):
print("自定义Excel数据处理")
def export(self):
print("导出Excel文件")
# 正面示例
pdf = PDFReport()
pdf.generate() # 复用通用流程
# 反面示例(重复代码)
class BadPDFReport:
def generate(self):
print("收集PDF数据")
print("通用数据处理") # 重复代码
print("导出PDF文档")
class BadExcelReport:
def generate(self):
print("收集Excel数据")
print("通用数据处理") # 重复代码
print("导出Excel文件")
14. 责任链模式(Chain of Responsibility)
场景:请求处理管道、中间件
优点:动态添加处理者
缺点:请求可能未处理
框架应用:Django中间件系统
class Handler(ABC):
def __init__(self, successor=None):
self.successor = successor
def handle(self, request):
if self.can_handle(request):
return self.process(request)
elif self.successor:
return self.successor.handle(request)
raise Exception("无法处理请求")
@abstractmethod
def can_handle(self, request): pass
@abstractmethod
def process(self, request): pass
class AuthHandler(Handler):
def can_handle(self, request):
return "auth" in request
def process(self, request):
print("身份验证通过")
class LogHandler(Handler):
def can_handle(self, request):
return True # 最终处理器
def process(self, request):
print(f"记录请求: {request}")
# 正面示例
pipeline = AuthHandler(LogHandler())
pipeline.handle({"action": "login", "auth": "token"})
# 反面示例(巨型处理函数)
def bad_handler(request):
if "auth" in request:
print("身份验证通过")
# ...其他条件分支...
print(f"记录请求: {request}") # 所有逻辑耦合
15. 命令模式(Command)
场景:GUI操作、事务管理
优点:解耦调用者和接收者
缺点:增加命令类数量
class Light:
def on(self): print("开灯")
def off(self): print("关灯")
class Command(ABC):
@abstractmethod
def execute(self): pass
class LightOnCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.on()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.off()
class RemoteControl:
def __init__(self):
self.history = []
def execute_command(self, command):
command.execute()
self.history.append(command)
def undo(self):
if self.history:
last = self.history.pop()
print("撤销操作: ", end="")
last.execute() # 简化:实际需实现反向操作
# 正面示例
light = Light()
remote = RemoteControl()
remote.execute_command(LightOnCommand(light))
remote.undo() # 支持撤销
# 反面示例(直接调用)
light.on() # 无法记录历史,不支持撤销
16. 状态模式(State)
场景:订单状态流转、游戏角色状态
优点:简化状态转换逻辑
缺点:增加状态类数量
class OrderState(ABC):
@abstractmethod
def next(self, order): pass
@abstractmethod
def prev(self, order): pass
class PendingState(OrderState):
def next(self, order):
order.state = PaidState()
def prev(self, order):
print("已是初始状态")
class PaidState(OrderState):
def next(self, order):
order.state = ShippedState()
def prev(self, order):
order.state = PendingState()
class Order:
def __init__(self):
self.state = PendingState()
def next_state(self):
print("转到下一状态")
self.state.next(self)
def __str__(self):
return type(self.state).__name__
# 正面示例
order = Order()
print(order) # PendingState
order.next_state()
print(order) # PaidState
# 反面示例(状态标志+条件分支)
class BadOrder:
def __init__(self):
self.status = "pending"
def next_state(self):
if self.status == "pending":
self.status = "paid"
elif self.status == "paid":
self.status = "shipped"
# 状态逻辑分散在各处
四、Python设计模式深度洞察
1.动态语言特性:Python的鸭子类型减少了对工厂模式的需求
2.装饰器内置支持:@decorator语法是装饰器模式的语法糖
3.模式混合使用:实际项目中常组合多种模式(如Observer + Command)
4.框架设计启示:
Django使用Template Method定义视图生命周期
Flask通过Decorator实现路由注册
SQLAlchemy的Session使用Proxy模式
五、为什么需要设计模式?—— 未使用模式的代价
问题场景 | 无模式方案 | 后果 | 适用模式 |
---|---|---|---|
全局配置管理 | 多个独立配置对象 | 配置不一致,资源浪费 | 单例模式 |
多支付网关支持 | if/else硬编码 | 添加新网关需修改核心逻辑 | 策略模式 |
跨平台UI开发 | 平台相关代码分散 | 维护困难,兼容性问题 | 抽象工厂 |
复杂对象构造 | 超长构造函数 | 参数混乱,构造逻辑复杂 | 建造者模式 |
事件通知系统 | 直接调用接收方 | 紧耦合,难以扩展新接收方 | 观察者模式 |