Python 中常见设计模式的教程:聚焦于继承、多态与行为模式
欢迎来到这个教程!我们将基于面向对象编程(OOP)的核心概念(如继承、多态),探讨几个常见的类似设计模式。这些模式常用于处理可变行为、接口一致性和系统扩展,比如你之前的通知系统设计(使用抽象基类实现多态)。教程将从基础解释开始,逐步深入到代码实现和实际应用。
我会用Python示例,因为它简单且支持抽象基类(ABC)。假设你有基本的Python知识(如类、继承)。每个模式后,我会比较它与你设计的相似性,并给出优化建议。
1. 准备工作:理解核心OOP概念
- 继承(Inheritance):子类从父类(或基类)获取属性和方法。用于代码复用,但过度使用可能导致紧耦合。
- 多态(Polymorphism):同一方法名在不同类中实现不同行为。通过基类引用调用子类方法。
- 抽象基类(ABC):使用
from abc import ABC, abstractmethod定义接口,强制子类实现抽象方法。
示例基础代码(你的通知系统简化版):
from abc import ABC, abstractmethod
class NotificationBot(ABC):
@abstractmethod
def send_message(self, message):
pass
class EmailBot(NotificationBot):
def send_message(self, message):
print(f"发送邮件: {message}")
class SmsBot(NotificationBot):
def send_message(self, message):
print(f"发送短信: {message}")
# 多态使用
def notify(bot: NotificationBot, msg: str):
bot.send_message(msg)
notify(EmailBot(), "Hello!") # 输出: 发送邮件: Hello!
这展示了继承(EmailBot/SmsBot 继承 NotificationBot)和多态(notify 函数统一调用)。
2. 策略模式(Strategy Pattern)
解释
策略模式将算法或行为封装成独立类,通过上下文类动态选择。适合当行为需要运行时切换时(如通知系统切换平台)。
- 为什么用?:避免if-else分支,提高灵活性。
- 组件:策略接口(抽象基类)、具体策略(子类)、上下文(使用策略的类)。
与你设计的相似性
你的NotificationBot就是策略接口,send_message是行为。相似,但策略模式更强调动态注入(e.g., setter方法)。
代码实现
from abc import ABC, abstractmethod
# 策略接口
class SortStrategy(ABC):
@abstractmethod
def sort(self, data):
pass
# 具体策略
class BubbleSort(SortStrategy):
def sort(self, data):
return sorted(data) # 简化实现
class QuickSort(SortStrategy):
def sort(self, data):
return sorted(data, reverse=True) # 简化
# 上下文
class Sorter:
def __init__(self, strategy: SortStrategy):
self.strategy = strategy
def set_strategy(self, strategy: SortStrategy):
self.strategy = strategy # 动态切换
def perform_sort(self, data):
return self.strategy.sort(data)
# 使用
sorter = Sorter(BubbleSort())
print(sorter.perform_sort([3, 1, 2])) # [1, 2, 3]
sorter.set_strategy(QuickSort())
print(sorter.perform_sort([3, 1, 2])) # [3, 2, 1]
应用场景
- 支付系统:策略为支付宝/微信。
- 优化你的设计:添加setter到NotificationBot,实现动态切换平台。
3. 模板方法模式(Template Method Pattern)
解释
基类定义算法骨架(固定步骤),子类实现可变部分。适合流程固定但细节变的情况。
- 为什么用?:确保核心流程一致,同时允许自定义。
- 组件:抽象基类(定义模板方法)、钩子方法(抽象,子类实现)。
与你设计的相似性
你的抽象方法send_message像钩子。如果添加通用步骤(如日志记录),就更像模板方法。
代码实现
from abc import ABC, abstractmethod
class Game(ABC):
def play(self): # 模板方法:固定流程
self.initialize()
self.start()
self.end()
@abstractmethod
def initialize(self):
pass
@abstractmethod
def start(self):
pass
@abstractmethod
def end(self):
pass
class Chess(Game):
def initialize(self):
print("设置棋盘")
def start(self):
print("开始下棋")
def end(self):
print("游戏结束")
# 使用
Chess().play()
# 输出:
# 设置棋盘
# 开始下棋
# 游戏结束
应用场景
- 报告生成:基类定义“加载数据 -> 处理 -> 输出”,子类自定义处理。
- 优化你的设计:在NotificationBot添加模板如
def notify(self, msg): self.log(); self.send_message(msg);,子类只实现send_message。
4. 桥接模式(Bridge Pattern)
解释
分离抽象和实现,使用组合(has-a)而非继承。适合多维度变化(如形状+颜色)。
- 为什么用?:避免继承爆炸,提高独立扩展。
- 组件:抽象(接口)、实现(独立接口)、桥接(抽象持有实现)。
与你设计的相似性
你的设计用继承;桥接用组合,更灵活。如果你的Bot有多个变体(如协议+平台),桥接更好。
代码实现
from abc import ABC, abstractmethod
# 实现接口
class Color(ABC):
@abstractmethod
def fill(self):
pass
class Red(Color):
def fill(self):
return "红色"
class Blue(Color):
def fill(self):
return "蓝色"
# 抽象接口(桥接)
class Shape(ABC):
def __init__(self, color: Color):
self.color = color
@abstractmethod
def draw(self):
pass
class Circle(Shape):
def draw(self):
return f"画圆圈,颜色:{self.color.fill()}"
# 使用
print(Circle(Red()).draw()) # 画圆圈,颜色:红色
应用场景
- 设备驱动:抽象为设备,实现为平台(Windows/Linux)。
- 优化你的设计:让NotificationBot持有“协议实现”类,避免深继承。
5. 其他相关模式简述
- 抽象工厂(Abstract Factory):创建对象家族。扩展你的设计:工厂根据平台创建Bot实例。
- 适配器(Adapter):兼容旧接口。e.g., 适配第三方API到你的send_message。
6. 最佳实践与注意事项
- SOLID原则:你的设计符合“开闭原则”(扩展不修改)和“里氏替换”(子类可替基类)。
- 何时选择:小项目用策略/模板;复杂用桥接避免继承问题。
- 测试:用单元测试验证多态(e.g., mock子类)。
- Python特色:用duck typing(不强制ABC)简化,但ABC提升类型安全。
- 常见陷阱:过度设计——从简单继承开始,必要时重构。
7. 实践练习
- 扩展你的通知系统:添加微信Bot子类,实现send_message。
- 用策略模式重构排序示例,支持更多算法。
- 思考:如果通知需支持“加密+发送”,用桥接如何实现?
如果需要更详细代码、特定模式扩展,或基于你的代码修改,告诉我!