写在前面 · 模式是给痛点立的牌子

用白话把 GoF 23 种设计模式讲清楚。

作者 David更新于

先说一句可能得罪人的大实话:大部分人是先会背 23 个模式的名字,再慢慢忘光,最后在某次重构里自己重新发明了其中几个——然后才真正懂了它们。

这个系列想把顺序倒过来:先让你看见痛,再告诉你前人是怎么止痛的。

设计模式到底是个啥

把话说白了:设计模式就是前人在某个坑里摔多了,爬出来之后在坑边立的一块牌子,上面写着“这么走能绕过去”。

它不是语法,不是框架,不是你 import 进来就能用的库。它是一种在特定场景下反复被验证有效的对象组织套路。1994 年,四位作者(业内昵称 GoF,Gang of Four,“四人帮”)把当时面向对象界反复出现的 23 种套路收集成册,写了本《Design Patterns》,从此这 23 个就成了程序员的“普通话”——你说“这里用个观察者”,对面立刻懂,不用画半小时图。

所以模式最大的价值有两层:一层是解决方案本身(怎么写),另一层是词汇表(怎么沟通)。后者常被低估——团队里能用一个词对齐一整套设计,是极高效的事。

为什么会有这些痛点:一切都因为“变”

如果需求永远不变,世界上就不需要设计模式——一把梭把功能写完,能跑就行。

问题是需求一定会变。今天只支持支付宝,明天加微信,后天老板要加数字货币;今天导出 PDF,下周要导出 Excel。几乎所有设计模式,本质上都在回答同一个问题:当某个东西要变的时候,怎么让改动的影响范围最小?

GoF 有一句纲领性的话,值得刻在脑子里:

Encapsulate the concept that varies.(把“会变的那部分”封装隔离起来。)

你会发现,23 个模式几乎都是这句话在不同场景下的变体:策略模式隔离“会变的算法”,观察者模式隔离“会变的通知对象”,工厂模式隔离“会变的具体类”……看模式时别只盯着类图,要问一句:它到底在隔离什么变化? 抓住这条线,23 个模式就不再是 23 条孤立的口诀,而是一张网。

三大类,一句话分清

GoF 把 23 个模式按“管什么”分成三类,这个分法非常好记:

类别管什么一句话典型代表
创建型对象怎么生把 new 这件事管起来,别到处乱 new单例、工厂、建造者
结构型对象怎么拼把小对象组装成大结构,还不别扭适配器、装饰器、代理
行为型对象怎么处对象之间怎么分工、怎么通信策略、观察者、命令

创建型管“生”,结构型管“拼”,行为型管“处对象关系”——生、拼、处,三个字记一辈子。

每篇怎么讲

为了不写成第 101 本“设计模式速查手册”,本系列每个模式都按同一条线索展开,力求把“背名词”变成“懂痛点”:

  1. 这是什么 —— 先用一个现实生活里的例子把直觉建立起来(遥控器、咖啡加料、公司审批流……),再回到代码。
  2. 解决什么痛 —— 不先讲解法,先把“不用这个模式会有多难受”演示给你看。痛点不清,解法无感。
  3. 怎么实现 —— 给出 Go 的惯用实现(必要时对比 C++ / Java),不堆代码,只讲关键结构。
  4. 有哪些坑 —— 模式用错比不用还糟。这一节专讲过度设计、误用、以及“看起来像其实不是”的陷阱。
  5. 开源里怎么用 —— 到真实的知名项目(Go 标准库、Kubernetes、Java JDK、Nginx……)里,把这个模式活生生指给你看。

一句提醒贯穿全系列:模式是解药,不是维生素。没病别乱吃。见到痛点才用对应的模式,是工程师;为了用模式而制造痛点,是“模式病”。本系列每一篇的“坑”小节,有一半篇幅在劝你别乱用。

关于代码

  • 主语言 Go:用 Go 的惯用法(小接口、组合、函数值、error 返回)来写,你会发现不少“经典 OOP 模式”在 Go 里轻得几乎看不见——这本身就很说明问题。
  • 辅以 C++ / Java:在能体现差异的地方,顺手对比一下 C++ 和 Java 的写法,看看同一个痛点在不同类型系统下怎么止。
  • 完整可运行代码都在配套开源仓库,9 种语言对照实现,建议边读边跑: 👉 github.com/davidapp/GoF

准备好了就从单例模式开始——它最简单,却也是争议最大、被骂最多的一个,适合用来热身。

本页目录