【Design Patterns】23 Design Patterns: The Ultimate Developer‘s Toolkit

文章目录

23种设计模式:程序员的"超级英雄工具箱"

1995 年,GoF(Gang of Four,四人组)合作出版了《设计模式:可复用面向对象软件的基础》(《Design Patterns: Elements of Reusable Object-Oriented Software》)一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。

很多人第一次看到《设计模式》这本书时,都会被吓到:

  • 工厂方法
  • 抽象工厂
  • 访问者
  • 享元

光名字就像魔法咒语一样。

其实设计模式没有那么神秘。

如果把程序员比作超级英雄,那么设计模式就是他们随身携带的 23件神器

遇到不同的问题,就拿出不同的工具解决。

这些工具被分成三大类:

分类 作用
创建型 如何创建对象
结构型 如何组合对象
行为型 如何让对象合作

一、创建型模式(5种)

1. 工厂方法(Factory Method)

小故事

你去冰淇淋店:

我要巧克力味!

店员直接递给你。

你不需要知道:

  • 牛奶放多少
  • 巧克力怎么融化
  • 冷冻多久

只需要告诉工厂:

我想要什么

解决什么问题

把"创建对象"的工作交给专门的工厂。

程序里的样子

python 复制代码
icecream = Factory.create("chocolate")

真实场景

YOLO加载模型

python 复制代码
model = create_model("yolov8")

内部:

python 复制代码
if name=="yolov8":
    return YOLOv8()

if name=="rt-detr":
    return RTDETR()

用户不需要知道具体创建过程。

常见应用

  • 数据集加载器
  • 模型加载器
  • 数据库驱动加载

2. 抽象工厂(Abstract Factory)

小故事

你来到主题餐厅。

你点:

海洋套餐

结果得到:

  • 海盗船餐盘
  • 贝壳饼干
  • 蓝色饮料

它们是一整套风格统一的东西。

和工厂方法区别

工厂方法:

生产一个产品

抽象工厂:

生产一整套产品

真实场景

跨平台GUI开发

例如:

Qt

python 复制代码
factory.create_button()
factory.create_textbox()
factory.create_menu()

Windows工厂:

text 复制代码
WinButton
WinMenu
WinTextbox

Mac工厂:

text 复制代码
MacButton
MacMenu
MacTextbox

生成的是一整套同风格组件。


3. 建造者模式(Builder)

小故事

拼一个巨大的乐高机器人:

步骤1:

拼脑袋

步骤2:

拼身体

步骤3:

拼手脚

最后组装完成。

解决什么问题

复杂对象一步创建太麻烦。

拆成多个步骤完成。

真实场景

深度学习网络搭建

python 复制代码
model = (
    Builder()
    .add_backbone()
    .add_neck()
    .add_head()
    .build()
)

YOLO配置文件本质上就有 Builder 思想。

常见应用

  • Transformer构建
  • SQL构建器
  • Docker镜像构建

4. 原型模式(Prototype)

小故事

你画了一张特别漂亮的画。

同学都想要。

与其重新画十遍:

直接复印十份。

解决什么问题

复制已有对象比重新创建更快。

真实场景

数据增强

python 复制代码
img2 = img.copy()

复制样本后:

python 复制代码
flip()
rotate()
crop()

而不是重新读取。

常见应用

  • OpenCV Mat复制
  • 配置模板复制
  • 游戏角色复制

5. 单例模式(Singleton)

小故事

学校只有一个校长。

无论谁找校长:

找到的都是同一个人。

解决什么问题

保证系统里某个对象永远只有一个。

例如:

  • 配置中心
  • 日志系统
  • 数据库连接管理器

真实场景

数据库连接池

python 复制代码
db = DatabasePool.get_instance()

整个系统只维护一个连接池。

否则:

text 复制代码
用户A 创建连接池
用户B 创建连接池
用户C 创建连接池

内存和连接数直接爆炸。

常见应用

  • 日志系统
  • 配置中心
  • Redis连接池
  • GPU资源管理器

例如:

PyTorch 中 CUDA Context 基本也是全局共享思想。


在 AI 工程中的例子

你经常会写:

py 复制代码
model = YOLO("best.pt")

模型可能有:

300MB参数

如果每个请求都加载:

py 复制代码
request1:
    YOLO("best.pt")

request2:
    YOLO("best.pt")

request3:
    YOLO("best.pt")

变成:

py 复制代码
300MB
+300MB
+300MB

GPU 很快爆掉。

实际生产环境会:

py 复制代码
class ModelManager:
    _instance = None

启动时加载一次:

py 复制代码
model = YOLO("best.pt")

后续:

所有请求共享同一个模型

这也是单例思想。


不要记:单例模式 = 只能创建一个对象

而应该记:单例模式 = 为昂贵且需要共享的资源,提供唯一的全局访问入口。


二、结构型模式(7种)

6. 适配器模式(Adapter)

小故事

手机充电器是 Type-C。

插座是两孔。

怎么办?

用转换头。

解决什么问题

让原本不兼容的两个东西一起工作。

真实场景

OpenCV 转 PIL

python 复制代码
cv_img
 ↓
Adapter
 ↓
PIL.Image

例如:

python 复制代码
Image.fromarray(cv_img)

常见应用

  • Tensor转Numpy
  • ONNX转TensorRT
  • 不同API兼容

7. 桥接模式(Bridge)

小故事

画笔和颜色分开卖:

  • 毛笔
  • 钢笔

搭配:

  • 红色
  • 蓝色

可以自由组合。

解决什么问题

两个维度独立变化。

避免类爆炸。

真实场景

AI推理框架

模型:

text 复制代码
YOLO
RT-DETR
PP-YOLOE

设备:

text 复制代码
CPU
GPU
NPU

自由组合:

python 复制代码
YOLO + GPU
YOLO + NPU
RT-DETR + GPU

避免类爆炸。


8. 组合模式(Composite)

小故事

文件夹:

text 复制代码
作业
 ├─ 数学
 ├─ 英语
 └─ 图片

对于电脑来说:

  • 文件是对象
  • 文件夹也是对象

处理方式一样。

解决什么问题

统一处理:

  • 单个对象
  • 对象集合

真实场景

神经网络结构

text 复制代码
Model
├── Backbone
├── Neck
└── Head

每个模块还能继续拆。

PyTorch:

python 复制代码
nn.Sequential()

典型组合模式。


9. 装饰器模式(Decorator)

小故事

奶茶:

原版奶茶

加珍珠

加椰果

加奶盖

解决什么问题

不修改原对象。

动态增加功能。

真实场景

Python装饰器

python 复制代码
@cache
def infer():

或者

python 复制代码
@torch.no_grad()

本质:

text 复制代码
原函数
+
新功能

不修改原代码。

最经典案例

Flask

python 复制代码
@app.route("/")

10. 外观模式(Facade)

小故事

看电影:

你只按一下:

text 复制代码
开始播放

幕后却自动完成:

  • 开电视
  • 开音响
  • 调灯光

解决什么问题

给复杂系统提供简单入口。

真实场景

YOLO推理

用户:

python 复制代码
model.predict(img)

背后:

text 复制代码
预处理
↓
推理
↓
NMS
↓
后处理

全部隐藏。

用户只看到

python 复制代码
predict()

11. 享元模式(Flyweight)

小故事

王者荣耀里:

100个小兵长得一样。

系统不会真的创建100套模型。

而是:

text 复制代码
共享模型
+
各自坐标

解决什么问题

大量相似对象节省内存。

真实场景

目标检测标签

100万个框:

python 复制代码
person
person
person
person

不会存100万个字符串。

共享:

python 复制代码
class_names

只保存索引。

常见应用

  • 字符串池
  • 字典缓存
  • Embedding共享

12. 代理模式(Proxy)

小故事

明星不直接接电话。

粉丝先联系经纪人。

经纪人决定:

  • 转达
  • 拒绝
  • 排队

解决什么问题

通过代理控制访问。

常见:

  • 网络代理
  • 缓存代理
  • 权限代理

真实场景

Nginx反向代理

用户:

text 复制代码
浏览器
 ↓
Nginx
 ↓
后端服务

用户永远不知道真实服务器。

常见应用

Nginx

  • 权限代理
  • 缓存代理
  • RPC代理

三、行为型模式(11种)

13. 责任链模式(Chain of Responsibility)

小故事

请假条审批:

text 复制代码
班主任
 ↓
年级主任
 ↓
校长

一级处理不了再往上交。

核心

请求沿链条传递。

真实场景

请求过滤器

Spring Boot

text 复制代码
认证
 ↓
鉴权
 ↓
日志
 ↓
业务处理

一层层往下传。


14. 命令模式(Command)

小故事

遥控器。

按下:

text 复制代码
开电视

遥控器不用知道电视内部怎么工作。

核心

把请求封装成对象。

真实场景

Linux Shell

bash 复制代码
rm a.txt

命令对象:

text 复制代码
执行者
+
参数

统一执行。

常见应用

  • Undo
  • Redo
  • 任务队列

15. 解释器模式(Interpreter)

小故事

数学表达式:

text 复制代码
1 + 2 × 3

你按照数学规则解释。

得到:

text 复制代码
7

核心

定义语言规则并解释执行。

真实场景

SQL解析器

sql 复制代码
SELECT * FROM user

数据库解释执行。

常见应用

  • SQL
  • 正则表达式
  • DSL语言

16. 迭代器模式(Iterator)

小故事

翻书。

你只需要:

text 复制代码
下一页

不用关心书是怎么装订的。

核心

顺序访问集合。

真实场景

PyTorch DataLoader

python 复制代码
for batch in dataloader:

你不知道数据来自:

  • 图片
  • 视频
  • LMDB

统一访问。


17. 中介者模式(Mediator)

小故事

机场塔台。

所有飞机都不直接互相联系。

统一联系塔台。

为什么比裁判更准确?

因为中介者最重要的是:

减少对象之间的直接联系

塔台是经典例子。

真实场景

消息队列

例如:

Apache Kafka

text 复制代码
服务A
  ↓
Kafka
  ↓
服务B

A和B无需直接通信。

好处

降低耦合。


18. 备忘录模式(Memento)

小故事

游戏存档。

失败后:

text 复制代码
读档重来

核心

保存并恢复历史状态。

真实场景

训练Checkpoint

python 复制代码
torch.save()

保存:

text 复制代码
权重
优化器
epoch

恢复:

python 复制代码
resume=True

这就是标准备忘录模式


19. 观察者模式(Observer)

小故事

关注UP主。

UP主更新:

所有粉丝收到通知。

核心

一对多通知机制。

真实场景

TensorBoard

训练过程中:

text 复制代码
Loss变化
 ↓
通知
 ↓
TensorBoard更新

常见应用

  • 消息订阅
  • GUI事件
  • WebSocket

20. 状态模式(State)

小故事

自动售货机:

没投币:

text 复制代码
不能出货

投币后:

text 复制代码
可以买饮料

核心

状态不同,行为不同。

真实场景

PyTorch Module

python 复制代码
model.train()

状态:

text 复制代码
Train

或者:

python 复制代码
model.eval()

状态:

text 复制代码
Eval

BatchNorm行为完全不同。


21. 策略模式(Strategy)

小故事

导航软件:

去学校:

  • 步行
  • 骑车
  • 坐公交

随时切换。

核心

同一个目标,多种实现方案。

真实场景

优化器

python 复制代码
optimizer = SGD()

或者

python 复制代码
optimizer = Adam()

或者

python 复制代码
optimizer = AdamW()

目标一样:

text 复制代码
更新参数

实现策略不同。


22. 模板方法模式(Template Method)

小故事

泡方便面:

固定步骤:

text 复制代码
烧水
↓
泡面
↓
等待

不同品牌:

调料不同。

核心

框架固定,细节可变。

真实场景

训练框架

例如:

PyTorch Lightning

框架固定:

text 复制代码
train()
 ↓
forward()
 ↓
loss()
 ↓
backward()

用户只重写:

python 复制代码
training_step()

即可。


23. 访问者模式(Visitor)

小故事

医院体检。

医生来到:

  • 小朋友
  • 大人
  • 老人

面前。

同样是医生。

面对不同人:

检查方式不同。

核心

不修改对象本身。

新增操作更容易。

真实场景

ONNX图优化

text 复制代码
Conv
Relu
BatchNorm

优化器遍历节点:

python 复制代码
visit(conv)
visit(relu)
visit(bn)

执行不同操作。

常见应用

  • 编译器AST遍历
  • ONNX优化
  • TensorRT图优化

一张图记住23种设计模式

text 复制代码
创建对象
├─ 工厂方法
├─ 抽象工厂
├─ 建造者
├─ 原型
└─ 单例

组织对象
├─ 适配器
├─ 桥接
├─ 组合
├─ 装饰器
├─ 外观
├─ 享元
└─ 代理

对象协作
├─ 责任链
├─ 命令
├─ 解释器
├─ 迭代器
├─ 中介者
├─ 备忘录
├─ 观察者
├─ 状态
├─ 策略
├─ 模板方法
└─ 访问者

设计模式在日常开发过程中发挥什么作用,感觉很无感,什么时候会用到

这是很多工程师学习设计模式时最真实的感受:

看书的时候感觉很厉害,工作的时候感觉完全用不上。

实际上,大部分程序员都是:

text 复制代码
先写代码
↓
代码越来越乱
↓
发现问题
↓
设计模式突然出现了

而不是:

text 复制代码
先学23种设计模式
↓
再开始写代码

(1)为什么会觉得设计模式没用?

因为你现在面对的问题可能还不够复杂。

例如:

python 复制代码
if model == "yolo":
    infer_yolo()

elif model == "rtdetr":
    infer_rtdetr()

完全没问题。

甚至:

python 复制代码
if ...
elif ...
elif ...
elif ...

几十行代码也能跑。

这时候你看策略模式:

python 复制代码
strategy.infer()

会觉得:

不是脱裤子放屁吗?


(2)什么时候开始有感觉?

假设你维护一个 AI 推理平台。

最开始:

python 复制代码
if model == "yolo":
    ...

elif model == "rtdetr":
    ...

后来新增:

text 复制代码
YOLOv5
YOLOv8
YOLOv11
RT-DETR
PP-YOLOE
GroundingDINO
SAM

代码变成:

python 复制代码
if ...
elif ...
elif ...
elif ...
elif ...
elif ...

500 行。

每次新增模型:

都要修改这里。

这时候你会开始烦。


然后有人写成:

python 复制代码
class InferStrategy:
    def infer(self):
        pass
python 复制代码
class YOLOStrategy:
    ...
python 复制代码
class RTDETRStrategy:
    ...

调用:

python 复制代码
strategy.infer()

新增模型:

python 复制代码
class SAMStrategy:
    ...

直接注册即可。

你忽然发现:

原来策略模式不是为了炫技,是为了少改代码。


(3)设计模式真正解决什么问题?

设计模式很少解决:

text 复制代码
算法问题
数学问题
性能问题

它主要解决:

text 复制代码
代码组织问题
团队协作问题
扩展维护问题

(4)举个YOLO项目例子

你最开始可能这么写:

python 复制代码
def train():
    ...

def validate():
    ...

def export():
    ...

很简单。


后来需求来了:

text 复制代码
支持检测
支持分割
支持姿态估计
支持分类

于是:

python 复制代码
if task == "detect":
    ...

if task == "segment":
    ...

if task == "pose":
    ...

越来越乱。


后来变成:

python 复制代码
TaskFactory.create(task)

这就是工厂模式。

你可能根本没想过:

哦,原来我在用设计模式。


(5)很多人天天在用设计模式

只是自己不知道。

例如 Python 装饰器:

python 复制代码
@torch.no_grad()

这就是装饰器模式。


PyTorch:

python 复制代码
model.train()
model.eval()

这就是状态模式。


优化器:

python 复制代码
SGD
Adam
AdamW

统一接口:

python 复制代码
optimizer.step()

这就是策略模式。


DataLoader:

python 复制代码
for batch in dataloader:

这是迭代器模式。


Checkpoint:

python 复制代码
torch.save()
torch.load()

这是备忘录模式。


你每天都在用。

只是没喊它们名字。


(6)什么时候应该主动想到设计模式?

有一个特别简单的判断标准:

当你开始频繁写下面这些东西时。


  1. 到处都是 if-else

例如:

python 复制代码
if model == "yolo":
python 复制代码
if model == "rtdetr":
python 复制代码
if model == "sam":

说明:

text 复制代码
工厂模式
策略模式

可能该上场了。


  1. 到处复制粘贴

例如:

python 复制代码
infer_yolo_cpu()
infer_yolo_gpu()
infer_yolo_npu()

大量重复。

说明:

text 复制代码
桥接模式
模板方法模式

可能能简化结构。


  1. 一个类超过2000行

你打开:

python 复制代码
infer.py

发现:

text 复制代码
2864行

里面:

text 复制代码
加载模型
预处理
推理
后处理
日志
监控
导出

全在一起。

这时候:

text 复制代码
组合模式
责任链模式

开始有价值。


  1. 新需求来了就要改老代码

例如:

新增一个模型。

必须修改:

text 复制代码
infer.py
train.py
export.py

十几个文件。

这通常说明:

代码没有遵守开闭原则(对扩展开放,对修改关闭)。

设计模式很多时候就是在帮助实现这一点。


(7)设计模式像什么?

很多人以为:

text 复制代码
设计模式 = 编程技巧

其实更像:

text 复制代码
设计模式 = 建筑经验

盖狗窝:

text 复制代码
随便搭

没问题。


盖三层楼:

text 复制代码
开始需要图纸

盖摩天大楼:

text 复制代码
必须有成熟架构

否则必塌。


(8)AI工程里最值得掌握的几个

如果你主要做:

  • YOLO
  • PyTorch
  • TensorRT
  • MNN
  • 大模型推理

优先掌握:

模式 为什么
工厂模式 模型注册、组件创建
策略模式 不同算法切换
组合模式 网络结构组织
装饰器模式 Python天天用
单例模式 模型管理、线程池
责任链模式 推理Pipeline
模板方法模式 训练框架

这 7 个模式已经覆盖了绝大多数 AI 工程场景。


从工程经验来看,设计模式最大的价值往往不是"让我写出更高级的代码",而是:

当项目从 1 万行代码长到 10 万行代码、从 1 个人开发变成 10 个人协作时,代码还能持续演进,而不是越改越乱。

很多时候,你不是先决定"我要用策略模式",而是在维护一个越来越复杂的系统时,发现某种设计模式恰好是解决当前痛点的最佳经验总结。

结语

很多人学习设计模式时,总想先记住 UML 图、类图和各种代码模板。

实际上恰恰相反。

真正重要的不是代码写法,而是:

当你遇到问题时,能想到有没有前人已经总结好的解决方案。

设计模式本质上不是 23 个固定套路,而是 23 条被无数程序员验证过的经验。

对于初学者来说,可以先记住一句话:

设计模式不是让代码变复杂,而是让复杂的代码变简单。

当你写的项目越来越大、合作的人越来越多时,就会发现这23个"超级英雄工具",正在悄悄帮你解决各种问题。

相关推荐
吴声子夜歌1 天前
Java面试——设计模式(一)
java·设计模式·面试
吴声子夜歌1 天前
Java面试——设计模式(二)
java·设计模式·面试
晨米酱1 天前
Umi Mock 如何从文件声明变成 HTTP 响应
前端·javascript·设计
Larcher2 天前
SDD 项目开发步骤与提示词
人工智能·设计模式·架构
阿无,2 天前
设计模式之责任链模式
设计模式·责任链模式
星期一研究室2 天前
为什么有些文档你永远不想打开第二次
微服务·产品·设计
云深处@2 天前
【C++设计模式】命令模式
c++·设计模式·命令模式
用户6919026813392 天前
Agent 上下文记忆原理
设计模式·架构·设计
Java后端的Ai之路2 天前
02、Python普通工厂模式
开发语言·人工智能·python·设计模式·普通工厂模式
Java后端的Ai之路2 天前
01、Python - 设计模式介绍
java·人工智能·python·设计模式·通用