Python 设计模式
设计模式是软件开发中针对常见问题的可重用解决方案。它们不是可以直接转换为代码的完整设计,而是解决特定问题的模板或蓝图。
设计模式的核心价值
设计模式就像建筑领域的标准图纸,为软件开发提供了以下好处:
- 提高代码复用性:避免重复造轮子
- 增强代码可维护性:使代码结构更清晰
- 促进团队协作:提供统一的编程语言和思维方式
- 提升代码质量:经过实践检验的解决方案更可靠
生活中的设计模式类比
想象你要建造一栋房子:
- 原始方式:每次从零开始设计,容易出错且效率低下
- 使用设计模式:使用标准的建筑图纸,知道客厅、厨房、卧室的标准布局方式
设计模式就是软件开发的"标准建筑图纸"。
设计模式的类型
根据经典著作 《Design Patterns - Elements of Reusable Object-Oriented Software》(中文译名:《设计模式:可复用的面向对象软件元素》) 的定义, 共有 23 种经典设计模式。这些模式按其关注点可分为三大类: 创建型模式(Creational Patterns)、结构型模式(Structural Patterns)和行为型模式(Behavioral Patterns)。 此外,在企业级开发中,还有一类常用的架构级设计模式。
| 序号 | 模式 & 描述 | 包括 |
|---|---|---|
| 1 | 创建型模式 用于解决对象的创建问题,通过封装实例化逻辑,隐藏具体实现细节,让系统在创建对象时更灵活、更可扩展。 |
|
| 2 | 结构型模式 关注类与对象的组合与协作,帮助我们构建灵活、可复用、可扩展的系统结构。 |
|
| 3 | 行为型模式 关注对象间的通信与职责分配,通过封装算法、状态或请求逻辑,提升系统的灵活性与可维护性。 |
|
| 4 | 企业级架构模式 这些模式常用于大型系统的分层架构中,关注表现层与业务逻辑层的协作。 |
|
下面的图片展示了各类设计模式之间的关系与层次结构:
设计模式的优点
- 提供统一的设计语言,使开发者能快速沟通设计意图。
- 为常见问题提供成熟、可复用的解决方案。
- 降低系统耦合度,提高代码的可维护性与可扩展性。
- 减少重复设计,提升开发效率与代码质量。
- 帮助新成员快速理解系统架构与设计思想。
设计模式的六大原则
1、开闭原则(Open-Closed Principle)
对扩展开放,对修改关闭。软件应能通过扩展新功能,而非修改已有代码来适应变化。实现这一原则的核心在于使用抽象(接口或基类)定义稳定的行为。
2、里氏替换原则(Liskov Substitution Principle)
任何基类出现的地方,子类都应该可以替代。只有当派生类能完全替代基类时,继承才有意义。这一原则保证了多态的正确性,是开闭原则的重要补充。
3、依赖倒置原则(Dependency Inversion Principle)
高层模块不应依赖低层模块,两者都应依赖抽象。具体实现应依赖接口或抽象类,而不是直接依赖具体类。该原则使系统更易于扩展与测试。
4、接口隔离原则(Interface Segregation Principle)
一个类不应该依赖它不需要的接口。应将大接口拆分为多个更小、更专用的接口,以降低耦合、提高灵活性。
5、迪米特法则(Law of Demeter)
又称"最少知道原则":一个对象应尽量减少与其他对象的交互。换言之,一个类应只了解与自己直接相关的对象,从而降低系统复杂度。
6、合成复用原则(Composite Reuse Principle)
优先使用组合或聚合关系来实现复用,而非继承。继承会造成强耦合,而组合能在运行时灵活替换依赖,实现更优雅的结构设计。
Python 中常用的设计模式示例
让我们通过几个具体的例子来理解设计模式在 Python 中的应用。
单例模式(Singleton)
单例模式确保一个类只有一个实例,并提供一个全局访问点。
实例
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
print("创建新的数据库连接")
return cls._instance
def connect(self):
print("连接到数据库")
# 使用示例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(f"db1 和 db2 是同一个实例吗?{db1 is db2}") # 输出:True
应用场景:
- 数据库连接池
- 配置管理器
- 日志记录器
工厂模式(Factory)
工厂模式提供创建对象的接口,让子类决定实例化哪个类。
实例
# 抽象产品
class Notification(ABC):
@abstractmethod
def send(self, message: str):
pass
# 具体产品
class EmailNotification(Notification):
def send(self, message: str):
print(f"发送邮件:{message}")
class SMSNotification(Notification):
def send(self, message: str):
print(f"发送短信:{message}")
# 工厂类
class NotificationFactory:
@staticmethod
def create_notification(notification_type: str) -> Notification:
if notification_type == "email":
return EmailNotification()
elif notification_type == "sms":
return SMSNotification()
else:
raise ValueError("不支持的通知类型")
# 使用示例
email = NotificationFactory.create_notification("email")
sms = NotificationFactory.create_notification("sms")
email.send("您的订单已发货")
sms.send("验证码:123456")
代码说明:
Notification是抽象基类,定义接口EmailNotification和SMSNotification是具体实现NotificationFactory负责创建具体的通知对象
观察者模式(Observer)
观察者模式定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。
实例
# 观察者接口
class Observer(ABC):
@abstractmethod
def update(self, message: str):
pass
# 具体观察者
class EmailSubscriber(Observer):
def __init__(self, name: str):
self.name = name
def update(self, message: str):
print(f"{self.name} 收到邮件通知:{message}")
class SMSSubscriber(Observer):
def __init__(self, name: str):
self.name = name
def update(self, message: str):
print(f"{self.name} 收到短信通知:{message}")
# 主题(被观察者)
class NewsPublisher:
def __init__(self):
self._subscribers = []
def subscribe(self, subscriber: Observer):
self._subscribers.append(subscriber)
def unsubscribe(self, subscriber: Observer):
self._subscribers.remove(subscriber)
def notify_subscribers(self, message: str):
for subscriber in self._subscribers:
subscriber.update(message)
# 使用示例
publisher = NewsPublisher()
# 创建订阅者
alice = EmailSubscriber("Alice")
bob = SMSSubscriber("Bob")
# 订阅新闻
publisher.subscribe(alice)
publisher.subscribe(bob)
# 发布新闻
publisher.notify_subscribers("Python 3.12 发布了!")
# 取消订阅
publisher.unsubscribe(alice)
publisher.notify_subscribers("这是只有 Bob 能看到的通知")
设计模式在 Python 中的特殊考虑
Python 的动态特性
Python 作为动态语言,有些设计模式实现起来更简单:
实例
def create_payment(method):
payment_methods = {
'credit_card': CreditCardPayment,
'paypal': PayPalPayment,
'alipay': AlipayPayment
}
return payment_methods[method]()
# 直接使用,无需复杂的类层次结构
payment = create_payment('alipay')
装饰器模式的内置支持
Python 内置了装饰器语法,让装饰器模式实现更优雅:
实例
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行时间:{end - start:.2f}秒")
return result
return wrapper
@log_execution_time
def process_data(data):
# 模拟数据处理
import time
time.sleep(1)
return f"处理后的数据:{data}"
# 使用
result = process_data("示例数据")
点我分享笔记