设计模式(Design Pattern)是软件开发中经过验证的最佳实践,用于解决在软件设计中常见的问题。
经典设计模式可分为三种:
| 类型 | 关注点 |
|---|---|
| 创建型(本章节) | 对象怎么来 |
| 结构型 | 对象怎么组装 |
| 行为型 | 对象间怎么协作 |
工厂方法
定义一个用于创建对象的接口,让子类决定实例化那个类
你是鹿幸咖啡的市场部门,经调研决定,每家门店在原有咖啡品类的产品上,集合当地特殊推出城市限定品类:
| 分店 | 做的咖啡 |
|---|---|
| 北京店 | 老北京豆汁拿铁 |
| 福州店 | 茉莉花茶美式 |

工厂模式核心价值体现在,总部(CoffeeShop)无需关注所有地方店铺的细节,每开家新地方店,就不需要修改总部的代码
# 不然你要这么写
class CoffeeShop:
def localOrder(self, city: str):
if city == "北京":
coffee = BeanJuiceLatteCoffee() # 硬编码
elif city == "福州":
coffee = JasmineTeaAmericanoCoffee()
# 每开一家新店,就要改这个类
抽象工厂
相比前者,不是在造一个东西,而是造”一整套”东西,而且这套东西的风格必须一致,不能混搭。
你去买家具,店里按风格分成了两个区:
| 现代简约风 | 中式复古风 | |
|---|---|---|
| 沙发 | 灰色布艺、细金属腿 | 红木雕花 |
| 茶几 | 钢化玻璃、极简 | 实木榫卯、带雕花 |
你可以选现代风,也可以选复古风,但不能混搭。客厅里放一张红木沙发配北欧风极简茶几,会非常难看。
当然,你乐意你随意

相较于前者,抽象工厂的特点就是,把”配套”这件事交给工厂,客户端永远拿不到混搭的结果。
| 工厂方法 | 抽象工厂 | |
|---|---|---|
| 管几个产品 | 一个产品(一个等级结构) | 一族产品(多个等级结构) |
| 工厂的样子 | 一个工厂一个方法,造一种东西 | 一个工厂一堆方法,造一整套 |
| 约束力 | 只管”怎么造出来” | 还要管”造出来的东西能不能配在一起” |
| 类比 | 单点菜单:每家店只卖汉堡,口味不同 | 套餐:汉堡+薯条+可乐,必须成套出 |
| 本例如果退化 | create_sofa() 单独抽出去 → 工厂方法 | 三个 create_xxx 合在一个工厂里 → 抽象工厂 |
想加一个新风格(比如”叙利亚风”),只需新建 Factory + 三个对应产品类,客户端和老代码一行不改。
生成器/创造者
对象的构建与表示分离,使同样的构建过程可以创建不同的表示
一份三明治可以分为三部分,面包、馅料、酱汁,但无论选择哪种组合,做三明治的过程简单且一致
如果使用构造函数:
Sandwich("法棍", "芥末", "金枪鱼") # 你认得出来那个参数是那个配料
使用生成器创建对象,一切就变得更加直观、优雅:
sandwich.bread("法棍").filling("金枪鱼").sauce("芥末").build()
类图很简单,如下:

class SandwichBuilder:
def __init__(self):
self._s = Sandwich()
def bread(self, name):
self._s.bread = name
return self # 返回自己,才能链式调用
def filling(self, name):
self._s.filling = name
return self
def sauce(self, name):
self._s.sauce = name
return self
def build(self):
s = self._s
self._s = Sandwich() # 重置,不然下一份会串味
return s
生成器模式其实非常适合超多属性对象的创建
原型
不想从头造一个,就照着现成的复制一份,改改细节接着用。
你是名应届毕业生,海投了100家公司,每家的简历内容 95% 一样,只有”应聘岗位”和”自我评价”两处不同。
你不会每次都重新写一遍,而是:写好一份底稿 → 修改→分别打印修改的版本。
这份底稿就是原型(Prototype),每次打印出来的就是克隆(clone)
就不画类图了,一个类就能实现:
class Resume:
def __init__(self, name: str):
self.name = name
self.age = 23
self.education = "XX大学 · 计算机 · 本科"
self.experience = ["A公司后端开发3年", "B公司架构师2年"]
self.target_job = "" # 每家不一样
self.self_eval = "" # 每家不一样
def clone(self):
"""克隆:照着自己复制一份"""
return copy.deepcopy(self) # 关键:深拷贝,一个新对象
master = Resume("张三")
job_a = master.clone()
job_a.target_job = "Java后端工程师"
job_a.self_eval = "熟悉高并发,抗压能力强"
job_b = master.clone()
job_b.target_job = "系统架构师"
job_b.self_eval = "有从0到1搭建微服务的经验"
原型模式主要解决的问题:有些对象创建成本很高(查数据库、读配置、噼里啪啦算半天),但它大部分状态是可以复用的,那就先造一个”样板”,后面全靠复制。
单例
一个类的实例,全世界只能有一个
一家公司可以有无数份文件、无数个员工、无数台电脑,但公章只有一枚。
- 张三去盖一个章,李四再去盖一个章;盖的是同一个章,印出来的效果完全一样。
- 如果行政部偷偷刻了第二枚章,两份合同上的印鉴不一样,公司就乱套了。
- 你不需要”新建一枚公章”,你只需要”拿到那枚公章”。
也只需要一个类就能演示,就不画图了:
class Seal:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
# 注意:__init__ 每次都会被调用!真正初始化要加保护(见下面的坑)
self.owner = "XX科技有限公司"
self.code = "1101080000001"
# 验证:三个人拿到的都是同一枚章
zhang_san = Seal()
li_si = Seal()
wang_wu = Seal()
print(zhang_san is li_si is wang_wu) # True
print(id(zhang_san), id(li_si), id(wang_wu)) # 三个数字完全一样
当然,实现方式多种多样,像什么饿汉式、懒汉式,挖坑后续更
参考资料:
《软件设计师教程》 - 清华大学出版社
《您的设计模式》 - 设计模式公司
一些AI给出的建议