在軟體開發中,當系統需要建立一系列相關或相互依賴的物件,而不想指定它們的具體類別時,抽象工廠模式是最佳選擇。本文將透過一個網路遊戲場景,深入淺出地講解這個模式的核心概念、實作細節與適用時機。
提供一個介面,用於建立一系列相關或相互依賴的物件,而無需指定它們具體的類別。這讓系統能夠獨立於其產品的建立、組合和表示方式。
想像我們正在開發一款類似 CS 的休閒 FPS 遊戲,支援 8-16 名玩家分組對戰。遊戲包含多張地圖,且地圖數量會持續增加。每個三維場景物體由兩個核心元素組成:模型(骨架)與紋理(表面材質)。
若在場景初始化時,程式碼直接根據地圖名稱具體化模型與紋理類別,每新增一張地圖就得修改初始化邏輯,嚴重違反開放封閉原則。這就是抽象工廠模式大展身手的時刻。
using System;
using System.Reflection;
namespace AbstractFactoryExample
{
class Program
{
static void Main(string[] args)
{
Patrix patrix = new Patrix();
patrix.LoadScene("HalfPaper");
patrix.LoadScene("Matrix");
}
}
class Patrix
{
private PatrixSceneFactory GetGameScene(string gameSceneName)
{
return (PatrixSceneFactory)Assembly.Load("AbstractFactoryExample")
.CreateInstance("AbstractFactoryExample." + gameSceneName);
}
public void LoadScene(string gameSceneName)
{
PatrixSceneFactory psf = GetGameScene(gameSceneName);
Texture texture = psf.CreateTexture();
Model model = psf.CreateModel();
model.FillTexture(texture);
}
}
abstract class PatrixSceneFactory
{
public abstract Model CreateModel();
public abstract Texture CreateTexture();
}
abstract class Model
{
public abstract void FillTexture(Texture texture);
}
abstract class Texture { }
class HalfPaper : PatrixSceneFactory
{
public override Model CreateModel() => new HalfPaperModel();
public override Texture CreateTexture() => new HalfPaperTexture();
}
class HalfPaperModel : Model
{
public HalfPaperModel() => Console.WriteLine("HalfPaper Model Created");
public override void FillTexture(Texture texture)
=> Console.WriteLine("HalfPaper Model is filled Texture");
}
class HalfPaperTexture : Texture
{
public HalfPaperTexture() => Console.WriteLine("HalfPaper Texture Created");
}
class Matrix : PatrixSceneFactory
{
public override Model CreateModel() => new MatrixModel();
public override Texture CreateTexture() => new MatrixTexture();
}
class MatrixModel : Model
{
public MatrixModel() => Console.WriteLine("Matrix Model Created");
public override void FillTexture(Texture texture)
=> Console.WriteLine("Matrix Model is filled Texture");
}
class MatrixTexture : Texture
{
public MatrixTexture() => Console.WriteLine("Matrix Texture Created");
}
}
Patrix.LoadScene 完全不動。Assembly.CreateInstance 依名稱實例化,消除對具體類別的編譯時依賴。ADO.NET 2.0 內建完整的抽象工廠體系:
CreateConnection、CreateCommand、CreateDataAdapter 等建立方法。DbConnection、DbCommand 等抽象類別,切換資料庫只需更換 Provider 字串,業務邏輯完全不變。CreateBot(),導致所有具體工廠都要修改。適用於「系列固定、產品族擴展」的場景。抽象工廠模式是處理「多維度變化」的利器:一個維度是產品系列(地圖/資料庫類型),另一個維度是產品類型(模型/紋理/連線/命令)。它將「建立什麼」與「如何建立」分離,讓系統在新增系列時優雅擴展。掌握其精髓,關鍵在於識別出系統中真正存在的「產品族」與「系列擴展點」。