🏭🔧三、 抽象工厂(Abstract Factory)——“成套生娃”一条龙(抽象工厂模式)

一句话:
不再只 new 一个披萨,而是一次性 new 整套原料家族(面团+酱料+芝士),
产品族之间严丝合缝、绝不混搭

1️⃣ 背景梗概:Factory Method 的“散装危机”

剧情 现场弹幕
纽约披萨用 薄面团 + 番茄酱 + Reggiano 芝士
芝加哥披萨用 厚面团 + 梅子酱 + Mozzarella 芝士
程序员 “我不想在 18 个具体类里分别拼原料!”

结论:
Factory Method 只管“生一个”,
抽象工厂升级成成套生产线,防止“天津煎饼配北京烤鸭”式灾难。

2️⃣ 官方定义(人话版)

“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。”

翻译:
老爸立遗嘱:“必须生一整套娃,且长相必须像一家人”,
至于到底是“纽约一家”还是“芝加哥一家”,由具体工厂拍板。

3️⃣ 角色演员表(新增)

角色 示例 职责
AbstractProduct 家族 DoughSauceCheese 抽象原料
ConcreteProduct 家族 ThinDoughPlumTomatoSauceReggianoCheese 具体原料
AbstractFactory PizzaIngredientFactory 接口 定义“成套创建”契约
ConcreteFactory NYPizzaIngredientFactory 真正 new 一整套
Client(披萨) CheesePizza 只面向抽象原料,不 care 产地

核心:
原料 new 从披萨类里彻底搬家到原料工厂。

4️⃣ 时序漫画(五格)

  1. 顾客:store.order("cheese")
  2. 店铺:new NYPizzaIngredientFactory() // 选族系
  3. 店铺:new CheesePizza(factory) // 把工厂注入披萨
  4. 披萨:dough = factory.createDough() // 薄面团
    sauce = factory.createSauce() // 番茄
    cheese = factory.createCheese() // Reggiano
  5. 披萨:prepare→bake→cut→box(全程零具体类

效果:
想换“芝加哥风味”?只改第 2 步注入 ChicagoIngredientFactory
披萨代码一行不动

5️⃣ 代码快照(伪 Java)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 抽象工厂
interface PizzaIngredientFactory {
    Dough createDough();
    Sauce createSauce();
    Cheese createCheese();
}

// 具体工厂 → 纽约家族
class NYPizzaIngredientFactory implements PizzaIngredientFactory {
    public Dough createDough() { return new ThinCrustDough(); }
    public Sauce createSauce() { return new MarinaraSauce(); }
    public Cheese createCheese() { return new ReggianoCheese(); }
}

// 客户端披萨
class CheesePizza extends Pizza {
    private PizzaIngredientFactory ingFactory;
    CheesePizza(PizzaIngredientFactory f) { this.ingFactory = f; }
    void prepare() {
        dough  = ingFactory.createDough();
        sauce  = ingFactory.createSauce();
        cheese = ingFactory.createCheese();
    }
}

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 打包成族系,
客户端只喊“给我一套”,
抽象工厂——专治混搭恐惧症