设计模式入门
设计模式入门
设计模式是解决软件设计中常见问题的可重用解决方案。Python作为一种动态语言,实现设计模式时有其独特的优雅之处。本文将介绍三种最常用的设计模式:单例、工厂和观察者模式。
单例模式
单例模式确保一个类只有一个实例,并提供全局访问点。在Python中,有多种实现方式:
使用__new__方法
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
if not self._initialized:
self.data = "初始化数据"
self._initialized = True
# 测试单例
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True,同一个实例
s1.data = "修改后的数据"
print(s2.data) # "修改后的数据",共享状态
使用装饰器
def singleton(cls):
"""单例装饰器"""
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
self.connection = "已连接"
print("数据库初始化完成")
# 无论创建多少次,都是同一个实例
db1 = Database()
db2 = Database()
print(db1 is db2) # True
使用模块级别
# config.py - 最简单的单例
class _Config:
def __init__(self):
self.debug = False
self.database_url = "sqlite:///default.db"
config = _Config() # 模块加载时创建,全局唯一
# 在其他模块中
# from config import config
# config.debug = True
工厂模式
工厂模式封装了对象的创建过程,将对象的创建与使用分离,提供更大的灵活性。
简单工厂
from abc import ABC, abstractmethod
class Shape(ABC):
"""图形抽象基类"""
@abstractmethod
def draw(self):
pass
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def draw(self):
return f"绘制圆形,半径={self.radius}"
def area(self):
return 3.14 * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def draw(self):
return f"绘制矩形,宽={self.width},高={self.height}"
def area(self):
return self.width * self.height
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def draw(self):
return f"绘制三角形,底={self.base},高={self.height}"
def area(self):
return 0.5 * self.base * self.height
class ShapeFactory:
"""图形工厂"""
_creators = {}
@classmethod
def register(cls, shape_type, creator):
cls._creators[shape_type] = creator
@classmethod
def create(cls, shape_type, **kwargs):
if shape_type not in cls._creators:
raise ValueError(f"未知的图形类型: {shape_type}")
return cls._creators[shape_type](**kwargs)
# 注册创建器
ShapeFactory.register("circle", Circle)
ShapeFactory.register("rectangle", Rectangle)
ShapeFactory.register("triangle", Triangle)
# 使用工厂
circle = ShapeFactory.create("circle", radius=5)
print(circle.draw()) # 绘制圆形,半径=5
print(f"面积: {circle.area()}") # 面积: 78.5
观察者模式
观察者模式定义了对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会自动收到通知并更新。
from typing import List, Dict, Any
import time
class EventEmitter:
"""事件发射器,实现观察者模式"""
def __init__(self):
self._listeners: Dict[str, List[callable]] = {}
def on(self, event: str, callback: callable):
"""注册事件监听器"""
if event not in self._listeners:
self._listeners[event] = []
self._listeners[event].append(callback)
return self # 支持链式调用
def emit(self, event: str, *args, **kwargs):
"""触发事件"""
if event in self._listeners:
for callback in self._listeners[event]:
callback(*args, **kwargs)
def remove_listener(self, event: str, callback: callable):
"""移除监听器"""
if event in self._listeners:
self._listeners[event] = [
cb for cb in self._listeners[event] if cb != callback
]
class OrderSystem:
"""订单系统,使用观察者模式"""
def __init__(self):
self.events = EventEmitter()
def create_order(self, order_id: str, amount: float):
"""创建订单"""
print(f"创建订单: {order_id}")
# 触发订单创建事件
self.events.emit("order_created", order_id=order_id, amount=amount)
def cancel_order(self, order_id: str):
"""取消订单"""
print(f"取消订单: {order_id}")
self.events.emit("order_cancelled", order_id=order_id)
# 订阅者:库存管理
def update_inventory(order_id: str, amount: float):
print(f"[库存] 更新库存,订单: {order_id}")
# 订阅者:发送通知
def send_notification(order_id: str, amount: float):
print(f"[通知] 发送订单确认邮件,订单: {order_id}")
# 订阅者:记录日志
def log_order(order_id: str, amount: float):
print(f"[日志] 记录订单: {order_id}, 金额: {amount}")
# 创建订单系统并订阅事件
order_system = OrderSystem()
order_system.events.on("order_created", update_inventory)
order_system.events.on("order_created", send_notification)
order_system.events.on("order_created", log_order)
# 创建订单,所有订阅者都会收到通知
order_system.create_order("ORD001", 99.99)
选择合适的模式
设计模式不是银弹,选择时需要考虑:
- 单例模式:适用于需要全局唯一实例的场景,如配置管理、数据库连接池
- 工厂模式:适用于对象创建逻辑复杂或需要根据条件创建不同类型对象的场景
- 观察者模式:适用于一对多的通知机制,如事件系统、消息队列
在Python中,由于其动态特性,很多模式的实现比静态语言更简洁。理解设计模式的核心思想,比死记硬背实现代码更重要。