當系統需要創建一組「相關或依賴」的物件,且這組物件有多個「產品族」(如麥當勞族、肯德基族)時,若直接在業務代碼中 new 具體類,將導致:
if/else 或 switch 判斷工廠類型,維護困難。抽象工廠模式通過定義一個「工廠介面」,每個具體工廠實現該介面,負責創建整個產品族的所有產品,客戶端僅面向介面編程,實現「產品族」與「客戶端」的解耦。
+-------------------+
| KuaiCanFactory | (抽象工廠介面)
| + eatJiTui():JiTui|
| + eatHanBao():HanBao|
+--------+----------+
^
+----------+----------+
| |
+-------+-------+ +-------+-------+
| MDLFactory | | KDJFactory | (具體工廠)
| + eatJiTui() | | + eatJiTui() |
| + eatHanBao() | | + eatHanBao() |
+-------+-------+ +-------+-------+
| |
v v
+-------+-------+ +-------+-------+
| MDLJiTui | | KDJJiTui | (具體產品:雞腿)
| + getJiTui() | | + getJiTui() |
+---------------+ +---------------+
+-------+-------+ +-------+-------+
| MDLHanBao | | KDJHanBao | (具體產品:漢堡)
| + getHanBao() | | + getHanBao() |
+---------------+ +---------------+
// 抽象產品:漢堡
public abstract class HanBao {
public abstract void GetHanBao();
}
public class MDLHanBao : HanBao {
public override void GetHanBao() => Console.WriteLine("麥當勞漢堡");
}
public class KDJHanBao : HanBao {
public override void GetHanBao() => Console.WriteLine("肯德基漢堡");
}
// 抽象產品:雞腿
public abstract class JiTui {
public abstract void GetJiTui();
}
public class MDLJiTui : JiTui {
public override void GetJiTui() => Console.WriteLine("麥當勞雞腿");
}
public class KDJJiTui : JiTui {
public override void GetJiTui() => Console.WriteLine("肯德基雞腿");
}
public abstract class KuaiCanFactory {
public abstract JiTui EatJiTui();
public abstract HanBao EatHanBao();
}
public class MDLFactory : KuaiCanFactory {
public override JiTui EatJiTui() => new MDLJiTui();
public override HanBao EatHanBao() => new MDLHanBao();
}
public class KDJFactory : KuaiCanFactory {
public override JiTui EatJiTui() => new KDJJiTui();
public override HanBao EatHanBao() => new KDJHanBao();
}
class Program {
static void Main() {
// 配置決定用哪家工廠,可從配置文件、DI 容器注入
KuaiCanFactory factory = new KDJFactory(); // 今天想吃肯德基
JiTui jiTui = factory.EatJiTui();
jiTui.GetJiTui(); // 輸出:肯德基雞腿
HanBao hanBao = factory.EatHanBao();
hanBao.GetHanBao(); // 輸出:肯德基漢堡
// 切換工廠,客戶端代碼完全不用動
factory = new MDLFactory();
factory.EatJiTui().GetJiTui(); // 麥當勞雞腿
factory.EatHanBao().GetHanBao(); // 麥當勞漢堡
}
}
只需新增三個類,零修改現有代碼:
public class PizzaHutJiTui : JiTui {
public override void GetJiTui() => Console.WriteLine("必勝客雞腿");
}
public class PizzaHutHanBao : HanBao {
public override void GetHanBao() => Console.WriteLine("必勝客漢堡");
}
public class PizzaHutFactory : KuaiCanFactory {
public override JiTui EatJiTui() => new PizzaHutJiTui();
public override HanBao EatHanBao() => new PizzaHutHanBao();
}
客戶端只需 `factory = new PizzaHutFactory();` 即可享用新口味。
public static class FactorySelector {
public static KuaiCanFactory Create(string brand) => brand switch {
"MDL" => new MDLFactory(),
"KDJ" => new KDJFactory(),
"PizzaHut" => new PizzaHutFactory(),
_ => throw new ArgumentException("未支援品牌")
};
}
// 使用
var factory = FactorySelector.Create(ConfigurationManager.AppSettings["FastFoodBrand"]);
抽象工廠模式的核心價值在於「封裝產品族的創建邏輯,讓客戶端免受具體工廠變更影響」。快餐店比喻生動詮釋了:
掌握「產品族 vs 產品等級」的變化維度,是正確選擇抽象工廠的關鍵。