🏭🔧三、 抽象工厂(Abstract Factory)——“成套生娃”一条龙(抽象工厂模式)
一句话:
不再只 new 一个披萨,而是一次性 new 整套原料家族(面团+酱料+芝士),
让产品族之间严丝合缝、绝不混搭!
1️⃣ 背景梗概:Factory Method 的“散装危机”
| 剧情 | 现场弹幕 |
|---|---|
| 纽约披萨用 薄面团 + 番茄酱 + Reggiano 芝士 | |
| 芝加哥披萨用 厚面团 + 梅子酱 + Mozzarella 芝士 | |
| 程序员 | “我不想在 18 个具体类里分别拼原料!” |
结论:
Factory Method 只管“生一个”,
抽象工厂升级成成套生产线,防止“天津煎饼配北京烤鸭”式灾难。
2️⃣ 官方定义(人话版)
“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。”
翻译:
老爸立遗嘱:“必须生一整套娃,且长相必须像一家人”,
至于到底是“纽约一家”还是“芝加哥一家”,由具体工厂拍板。
3️⃣ 角色演员表(新增)
| 角色 | 示例 | 职责 |
|---|---|---|
AbstractProduct 家族 |
Dough、Sauce、Cheese |
抽象原料 |
ConcreteProduct 家族 |
ThinDough、PlumTomatoSauce、ReggianoCheese… |
具体原料 |
AbstractFactory |
PizzaIngredientFactory 接口 |
定义“成套创建”契约 |
ConcreteFactory |
NYPizzaIngredientFactory… |
真正 new 一整套 |
Client(披萨) |
CheesePizza |
只面向抽象原料,不 care 产地 |
核心:
把原料 new 从披萨类里彻底搬家到原料工厂。
4️⃣ 时序漫画(五格)
- 顾客:
store.order("cheese") - 店铺:
new NYPizzaIngredientFactory()// 选族系 - 店铺:
new CheesePizza(factory)// 把工厂注入披萨 - 披萨:
dough = factory.createDough()// 薄面团
sauce = factory.createSauce()// 番茄
cheese = factory.createCheese()// Reggiano - 披萨:prepare→bake→cut→box(全程零具体类)
效果:
想换“芝加哥风味”?只改第 2 步注入ChicagoIngredientFactory,
披萨代码一行不动!
5️⃣ 代码快照(伪 Java)
|
|
6️⃣ 优点弹幕
- 产品族一致性√ 绝不会出现“厚面团 + 稀酱料”黑暗料理
- 易于切换产品族 运行期换工厂 = 换整套风格
- 客户端解耦√ 披萨只认识抽象原料,彻底与具体类绝缘
7️⃣ 缺点弹幕
- 支持新种类产品麻烦:
想加“Clams” → 抽象工厂、所有具体工厂、客户端全得改 → 又违反 OCP - 类数量再次爆炸:M 族 × N 产品 = M×N 个类
- 若族系之间差异不大 → 过度设计 smells
8️⃣ 适用场景
| 场景 | 例子 |
|---|---|
| 系统需多套可替换产品族 | Win/Mac 风格 UI 组件 |
| 客户端只使用接口 | JDBC 统一接口 + 不同厂商驱动 |
| 强一致性约束 | 汽车配饰:宝马族只能配宝马轮毂/方向盘 |
9️⃣ 三工厂模式对比速查表
| 维度 | Simple Factory | Factory Method | Abstract Factory |
|---|---|---|---|
| 抽象级别 | 无 | 单产品 | 产品族 |
| OCP | ❌ | ✅ 横向扩展 | ✅ 横向扩展,❌ 纵向新增 |
| 复杂度 | ⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 关键词 | 一个类包办 | 子类决定生谁 | 成套一起生 |
🔟 30 秒记忆口诀
“Simple 一个娃,Method 一个家,
Abstract 直接发整套学区房!
换族如换刀,一致到发丝,
想加新物种——全厂都翻车了。”
🎁 彩蛋:现实比喻
抽象工厂 = 宜家套装
“北欧风”套装里:桌子、椅子、台灯全是北欧配色;
想换“工业风”?整套一起换,绝不会出现“北欧桌 + 工业椅”精神分裂!
把原料 new 打包成族系,
客户端只喊“给我一套”,
抽象工厂——专治混搭恐惧症!