【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 小时前
18. 中介者模式(Mediator Pattern)
设计模式·c#·中介者模式
咖啡八杯2 小时前
GoF设计模式——外观模式
java·设计模式·外观模式
江湖中的阿龙3 小时前
23种设计模式
java·开发语言·设计模式
basketball6163 小时前
设计模式入门:7. 策略模式详解 C++实现
c++·设计模式·策略模式
thisiszdy3 小时前
<设计模式> 生产者-消费者模式
设计模式
刀法如飞12 小时前
AI时代:DDD领域驱动建模与Ontology语义建模的区别
java·设计模式·架构
skywalk81631 天前
你希望的「多路捕获」语法是哪种形式?具体而言,「捕获 类型为 e」指的是什么?
开发语言·编程
0x3F(小茶)1 天前
嵌入式C设计模式完全指南(基于《C嵌入式编程设计模式》)
c语言·开发语言·单片机·嵌入式硬件·设计模式