在軟體開發中,當系統需要建立一組相關或相互依賴的物件,且不想指定其具體類別時,抽象工廠模式便是最佳選擇。它比簡單工廠或工廠方法更進一步,能夠處理「多個產品等級結構」的建立問題。本文將透過生活化的軍事範例、UML 類圖解析、完整 C# 程式碼實作,以及 .NET 框架中的實際應用(DbProviderFactory),帶您徹底掌握此模式。
假設某國面臨戰爭,前期需生產「導彈」與「越野車」進行打擊,後期則轉為生產「核彈」與「主戰坦克」實施毀滅性打擊。這裡有兩個產品族(炸彈、坦克),每個族下又有多個具體產品。抽象工廠的核心在於:定義一個介面,讓具體工廠決定生產哪一族產品。

#region 炸彈系列
public abstract class Bomb
{
public abstract void Explode();
}
public class MissileBomb : Bomb
{
public override void Explode()
{
Console.WriteLine("我是一顆中國造導彈,來轟炸不老實的小邪惡國家!");
}
}
public class NuclearBomb : Bomb
{
public override void Explode()
{
Console.WriteLine("我是一顆中國造核彈,來轟炸不老實的小邪惡國家!");
}
}
#endregion
#region 坦克系列
public abstract class Tank
{
public abstract void Move();
}
public class OffroadVehicle : Tank
{
public override void Move()
{
Console.WriteLine("我是一輛中國造越野車,來踏平不老實的小邪惡國家!");
}
}
public class MainBattleTank : Tank
{
public override void Move()
{
Console.WriteLine("我是一輛中國造主戰坦克,來踏平不老實的小邪惡國家!");
}
}
#endregion
#region 中國兵工廠 (抽象工廠)
public abstract class ChinaFactory
{
public abstract Tank CreateTank();
public abstract Bomb CreateBomb();
}
#endregion
#region 具體工廠:前期生產線
public class EarlyWarFactory : ChinaFactory
{
public override Bomb CreateBomb() => new MissileBomb();
public override Tank CreateTank() => new OffroadVehicle();
}
#endregion
#region 具體工廠:後期生產線
public class LateWarFactory : ChinaFactory
{
public override Bomb CreateBomb() => new NuclearBomb();
public override Tank CreateTank() => new MainBattleTank();
}
#endregion
public class WarCommander
{
private Bomb _bomb;
private Tank _tank;
public WarCommander(ChinaFactory factory)
{
_bomb = factory.CreateBomb();
_tank = factory.CreateTank();
}
public void LaunchAttack()
{
_bomb.Explode();
_tank.Move();
}
}
public class Program
{
public static void Main()
{
// 前期作戰
ChinaFactory earlyFactory = new EarlyWarFactory();
WarCommander earlyCommander = new WarCommander(earlyFactory);
earlyCommander.LaunchAttack();
Console.WriteLine("按任意鍵,進入後期總攻...");
Console.ReadKey();
// 後期作戰:只需切換工廠實例
ChinaFactory lateFactory = new LateWarFactory();
WarCommander lateCommander = new WarCommander(lateFactory);
lateCommander.LaunchAttack();
Console.WriteLine("釣魚島是中國的,神聖不可侵犯!");
Console.ReadLine();
}
}

缺點:難以支援「新種類產品」的變化。若需新增產品類型(如增加「戰機」),必須修改抽象工廠介面及所有子類,違反開放-封閉原則。
適用場景:
System.Data.Common.DbProviderFactory.NET 資料提供者模型是抽象工廠的經典應用。DbProviderFactory 扮演抽象工廠,負責建立 DbConnection、DbCommand、DbDataAdapter 等一組相關物件。
// 抽象工廠角色
public abstract class DbProviderFactory
{
public virtual DbConnection CreateConnection() { ... }
public virtual DbCommand CreateCommand() { ... }
public virtual DbDataAdapter CreateDataAdapter() { ... }
// ... 其他建立方法
}
// 具體工廠:SQL Server 實作
public sealed class SqlClientFactory : DbProviderFactory
{
public static readonly SqlClientFactory Instance = new SqlClientFactory();
public override DbConnection CreateConnection() => new SqlConnection();
public override DbCommand CreateCommand() => new SqlCommand();
public override DbDataAdapter CreateDataAdapter() => new SqlDataAdapter();
// ... 針對 SQL Server 的具體實作
}
開發者只需依賴 DbProviderFactory 介面,即可在不修改業務代碼的情況下切換資料庫(如從 SQL Server 換成 Oracle),完美體現了抽象工廠的威力。
抽象工廠模式透過「工廠的工廠」結構,優雅地解決了多產品族、多產品等級的建立問題。雖然擴展新產品類型較困難,但在產品族固定、需保證族內一致性的場景下(如跨平台 UI 元件庫、資料庫驅動、遊戲陣營裝備系統),它是不可或缺的設計利器。