【Python】设计模式与架构思维(第十二阶段)
十二、设计模式与架构思维
阶段定位:设计模式是解决常见问题的经验总结,架构思维是站在系统层面思考问题的能力。本阶段不是教条式地背诵 23 种设计模式,而是理解模式的本质,学会在合适的场景选择合适的方案,最终形成自己的架构判断力。
1 | ┌──────────────────────────────────────────────────────────────────┐ |
1. 设计原则(SOLID)
在讲具体模式之前,先理解五条核心设计原则。它们是比模式更根本的东西。
1.1 单一职责原则(SRP)
一个类应该只有一个引起它变化的原因。
1 | # 反例:一个类做太多事 |
职责划分示意图:
1 | 反例:一个类承担多个职责 |
1.2 开闭原则(OCP)
对扩展开放,对修改关闭。
1 | # 反例:修改现有代码来添加新功能 |
开闭原则示意图:
1 | ┌───────────────────────┐ ┌───────────────────────────────┐ |
1.3 里氏替换原则(LSP)
子类应该能够替换父类,而不破坏程序的正确性。
1 | # 反例:子类破坏了父类的契约 |
里氏替换原则示意图:
1 | 反例:子类违反父类契约 |
1.4 接口隔离原则(ISP)
客户端不应该依赖它不需要的接口。
1 | # 反例:胖接口 |
接口隔离原则示意图:
1 | 反例:胖接口,被迫实现不需要的方法 |
1.5 依赖倒置原则(DIP)
高层模块不应该依赖低层模块,两者都应该依赖抽象。
1 | # 反例:高层模块依赖低层模块 |
依赖倒置原则示意图:
1 | 反例:高层依赖低层(紧耦合) |
2. 创建型模式
创建型模式关注对象的创建过程,将对象创建逻辑封装起来,使代码更加灵活。
2.1 工厂模式
将对象的创建与使用分离,通过工厂类统一创建对象。
1 | from abc import ABC, abstractmethod |
工厂模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
2.2 建造者模式
将复杂对象的构建过程与表示分离,使同样的构建过程可以创建不同的表示。
1 | class HttpRequest: |
建造者模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
2.3 单例模式
保证一个类只有一个实例,并提供一个全局访问点。
1 | import threading |
单例模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
2.4 原型模式
通过复制现有对象来创建新对象,而不是从头创建。
1 | import copy |
2.5 抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
1 | from abc import ABC, abstractmethod |
抽象工厂模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
3. 结构型模式
结构型模式关注如何将类和对象组合成更大的结构。
3.1 适配器模式
将一个类的接口转换成客户希望的另一个接口,使原本不兼容的类可以协同工作。
1 | from abc import ABC, abstractmethod |
适配器模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
3.2 装饰器模式(与 Python 装饰器的关系)
动态地给对象添加额外的职责。Python 的 @decorator 是装饰器模式的语法糖,但类级别的装饰器模式更灵活。
1 | class Coffee: |
装饰器模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
3.3 代理模式
为其他对象提供一个代理以控制对这个对象的访问。
1 | class Image: |
代理模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
3.4 组合模式
将对象组合成树形结构以表示”部分-整体”的层次结构。
1 | from abc import ABC, abstractmethod |
3.5 享元模式
运用共享技术有效地支持大量细粒度的对象。
1 | class Flyweight: |
3.6 门面模式
提供一个统一的接口,用来访问子系统中的一群接口。
1 | class CPU: |
4. 行为型模式
行为型模式关注对象之间的通信和职责分配。
4.1 观察者模式
定义对象间的一对多依赖,当一个对象状态改变时,所有依赖者都会收到通知。
1 | from typing import List |
观察者模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
4.2 策略模式
定义一系列算法,把它们封装起来,并使它们可以互相替换。
1 | from typing import Callable |
4.3 模板方法模式
定义算法的骨架,将一些步骤延迟到子类中实现。
1 | from abc import ABC, abstractmethod |
模板方法模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
4.4 责任链模式
将请求沿着链传递,直到有一个处理者处理它。
1 | from typing import Optional |
责任链模式结构:
1 | ┌─────────────────────────────────────────────────────────────┐ |
5. Pythonic 的架构模式
5.1 依赖注入
通过构造函数或参数传入依赖,而不是在内部创建依赖。
1 | from typing import Protocol |
依赖注入示意图:
1 | ┌─────────────────────────────────────────────────────────────┐ |
5.2 仓储模式(Repository)
将数据访问逻辑封装在抽象层中,使业务层与具体数据源解耦。
1 | from abc import ABC, abstractmethod |
5.3 单元工作模式(Unit of Work)
管理事务边界,确保一组操作要么全成功,要么全回滚。
1 | class UnitOfWork: |
6. 架构思维
6.1 分层架构
1 | 典型的 Web 应用分层: |
6.2 微服务拆分原则
1 | # 单体 vs 微服务的决策树 |
6.3 常见架构反模式
| 反模式 | 症状 | 解决 |
|---|---|---|
| 大泥球 | 代码耦合严重,改一处坏多处 | 模块化、重构、引入边界 |
| 面条代码 | 没有分层,业务逻辑散落在各处 | 引入分层架构、Service 层 |
| 上帝类 | 一个类几千行,什么都管 | 拆分职责、提取协作类 |
| 重复代码 | 同样的逻辑复制粘贴 | 提取函数/类、使用继承或组合 |
| 过早优化 | 在不需要的地方引入复杂设计 | YAGNI(You Ain’t Gonna Need It) |
| 过度工程 | 为了用模式而用模式 | 简单优先,按需引入复杂度 |
6.4 补充模式
命令模式(Command)
将请求封装为对象,支持参数化、队列、日志、撤销操作。
1 | from typing import List, Optional |
状态模式(State)
允许对象在内部状态改变时改变其行为,看起来就像改变了类。
1 | from abc import ABC, abstractmethod |
状态模式转换图:
1 | ┌──────────────────┐ |
7. 工作实战场景
7.1 重构大型单体应用
场景描述:接手一个 10000+ 行的单体应用,代码耦合严重,需要重构为模块化架构。
1 | # 问题:大泥球代码,所有逻辑混在一起 |
7.2 构建可扩展的插件系统
场景描述:需要构建一个支持插件扩展的应用框架。
1 | # 插件系统设计 |
7.3 实现事件驱动架构
场景描述:构建一个电商系统,订单创建后需要触发多个下游操作。
1 | # 事件驱动架构(观察者模式变体) |
8. 常见面试题汇总
8.1 SOLID 原则
Q1:什么是 SOLID 原则?分别解释每个原则。
A:
- SRP(单一职责):一个类只负责一件事
- OCP(开闭原则):对扩展开放,对修改关闭
- LSP(里氏替换):子类可以替换父类而不破坏功能
- ISP(接口隔离):客户端不应依赖不需要的接口
- DIP(依赖倒置):依赖抽象而非具体实现
Q2:为什么单一职责原则很重要?
A:
- 提高代码可维护性:修改一个功能不影响其他功能
- 提高代码可读性:每个类职责清晰
- 提高可测试性:职责单一的类更容易测试
Q3:开闭原则的核心思想是什么?如何实现?
A:核心思想是通过抽象和多态实现扩展。实现方式:
- 定义抽象接口/基类
- 通过继承或组合扩展功能
- 使用依赖注入解耦
8.2 创建型模式
Q4:工厂模式和抽象工厂模式的区别是什么?
A:
- 工厂模式:创建单一类型的对象(如不同类型的通知)
- 抽象工厂模式:创建一组相关或依赖的对象(如 UI 组件套件)
Q5:单例模式有什么优缺点?
A:
- 优点:全局唯一实例,节省资源,统一管理状态
- 缺点:难以测试(全局状态),可能导致代码耦合,并发问题需要处理
Q6:建造者模式适用于什么场景?
A:适用于创建复杂对象,需要分步骤构建,且构建过程可能有不同变体的场景:
- HTTP 请求对象(方法、URL、头、体)
- 配置对象(多个可选参数)
- 文档对象(标题、内容、格式)
8.3 结构型模式
Q7:装饰器模式和代理模式的区别是什么?
A:
- 装饰器模式:动态添加职责,关注功能扩展
- 代理模式:控制访问,关注权限控制、延迟加载等
Q8:适配器模式的使用场景是什么?
A:
- 集成旧系统与新系统(接口不兼容)
- 调用第三方库(接口不符合预期)
- 兼容不同版本的 API
Q9:组合模式的核心思想是什么?
A:将对象组合成树形结构,表示”部分-整体”关系,使单个对象和组合对象具有一致的接口。
8.4 行为型模式
Q10:观察者模式和发布订阅模式的区别是什么?
A:
- 观察者模式:同步通知,直接调用
- 发布订阅模式:异步通知,通过消息队列解耦
Q11:策略模式在 Python 中如何简洁实现?
A:可以直接使用函数作为策略,无需定义接口类:
1
2
3
4
5
6
7 def discount_10_percent(price):
return price * 0.9
class Order:
def __init__(self, price, discount_strategy):
self.price = price
self.discount_strategy = discount_strategy
Q12:责任链模式适用于什么场景?
A:请求需要经过多个处理步骤,且步骤顺序可能变化:
- 中间件链(如 Flask/Django 的中间件)
- 请求处理管道(认证 → 限流 → 验证 → 处理)
8.5 架构思维
Q13:什么是分层架构?各层职责是什么?
A:
- 表现层:处理请求/响应、路由、验证
- 业务层:业务逻辑、流程编排
- 数据层:数据库操作、缓存
- 领域层:核心业务规则、实体定义
Q14:什么时候应该拆分微服务?
A:
- 团队规模大(>10 人),需要并行开发
- 不同模块发布节奏差异大
- 有独立扩展需求
- 具备 DevOps 能力
Q15:什么是架构反模式?举几个例子。
A:反模式是常见的错误设计,导致维护困难:
- 大泥球:代码耦合严重
- 上帝类:一个类做太多事
- 面条代码:没有分层
- 过早优化:过度设计
9. 实战项目:电商订单管理系统
9.1 项目目标
开发一个完整的电商订单管理系统,涵盖:
- 订单创建与处理流程
- 状态管理
- 事件驱动通知
- 数据持久化
9.2 项目结构
1 | order_system/ |
9.3 核心代码
1 | # domain/order.py - 领域模型 |
9.4 使用示例
1 | python main.py |
9.5 项目扩展
- 持久化层:集成 SQLAlchemy 或 Django ORM
- API 层:使用 FastAPI 提供 RESTful API
- 缓存层:使用 Redis 缓存热门商品
- 消息队列:使用 RabbitMQ 替代简单的事件总线
- 事务管理:实现 Unit of Work 模式
- 权限控制:添加认证和授权中间件
附录:第十二阶段自检清单
- 理解并应用 SOLID 五大设计原则
- 使用工厂模式解耦对象创建
- 使用建造者模式构建复杂对象
- 使用适配器模式兼容不同接口
- 使用装饰器模式动态扩展功能
- 使用观察者模式实现事件驱动
- 使用模板方法模式定义算法骨架
- 使用依赖注入提高代码可测试性
- 使用仓储模式抽象数据访问层
- 理解分层架构和各层职责
- 能判断何时应该/不应该使用某种设计模式
- 使用状态模式管理对象生命周期
- 使用事件驱动架构解耦系统组件
- 识别并避免常见架构反模式
工程师寄语:设计模式是工具,不是教条。最好的代码是”没有模式的代码”——因为它足够简单,不需要模式。当你发现自己在生硬套用模式时,停下来想一想:是不是问题被过度复杂化了?架构的本质是管理复杂度,而不是增加复杂度。
学习建议:
- 从理解问题开始,而不是从模式开始
- 先写简单代码,遇到问题再考虑模式
- 在实际项目中尝试应用至少一种模式
- 定期回顾代码,思考是否有过度设计的地方
- 阅读优秀项目的源码,学习别人如何运用模式
