首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 設計模式(3):抽象工廠模式——創建協調物件族群的製造藝術

     編輯:關於.NET

前言:從「單一物件」到「物件家族」

工廠方法解決單一物件創建變化,但現實系統常面臨「一組相互依賴、必須協同工作的物件」創建需求:UI 庫的按鈕/文字框/視窗必須同風格;資料存取的連線/命令/參數/適配器必須同 Provider;遊戲場景的道路/房屋/管道必須同風格。抽象工廠模式(Abstract Factory Pattern)應運而生:提供一個創建一系列相關或相互依賴物件的介面,而無需指定它們具體的類別(GoF)。

核心結構:雙層平行階層

  • AbstractFactory:宣告創建各抽象產品的工廠方法
  • ConcreteFactory:實作創建具體產品族群
  • AbstractProduct:各產品類型的抽象介面
  • ConcreteProduct:屬於特定族群的具體產品實作

抽象工廠邏輯模型

抽象工廠物理模型

生活類比:汽車沖壓生產線

同一套沖壓設備(AbstractFactory),換模具(ConcreteFactory)即可生產不同車型的右車門、左車門、擋泥板、引擎蓋(Product Family)。模具確保同車型零件規格一致、裝配匹配。

汽車沖壓類比

深度實戰:薪資計算系統的跨國擴展

階段 1:中國企業單一實作


public class ChineseBonus { public double Calculate() => 4000 * 0.1; }
public class ChineseTax { public double Calculate() => (4000 + 400) * 0.4; }
public class Calculator {
    public void Compute() {
        var bonus = new ChineseBonus().Calculate();
        var tax = new ChineseTax().Calculate();
        Console.WriteLine($"Salary: {4000 + bonus - tax}"); // 2640
    }
}

單一國家結構

階段 2:美國企業需求——複製修改陷阱

複製整套類別改名 AmericanBonus、AmericanTax,修改 Calculator 引用。缺點:原始碼重複、切換需改代碼、無法動態擴展新國家。

複製修改結構

階段 3:介面抽象——還不夠


public interface IBonus { double Calculate(); }
public interface ITax { double Calculate(); }
public class ChineseBonus : IBonus { /* ... */ }
public class AmericanBonus : IBonus { /* ... */ }
// Calculator 仍需 new ChineseBonus() 或 new AmericanBonus(),仍有硬編碼

介面抽象結構

階段 4:引入工廠類別——還是要改代碼


public class Factory {
    public ITax CreateTax() => new ChineseTax(); // 切換國家仍需修改此類
    public IBonus CreateBonus() => new ChineseBonus();
}

階段 5:抽象工廠 + 配置驅動——終極形態


public abstract class AbstractFactory {
    public static AbstractFactory GetInstance() {
        string factoryName = ConfigurationManager.AppSettings["factoryName"];
        return string.IsNullOrEmpty(factoryName) ? null 
            : (AbstractFactory)Assembly.Load(factoryName).CreateInstance(factoryName);
    }
    public abstract ITax CreateTax();
    public abstract IBonus CreateBonus();
}

public class ChineseFactory : AbstractFactory {
    public override ITax CreateTax() => new ChineseTax();
    public override IBonus CreateBonus() => new ChineseBonus();
}
public class AmericanFactory : AbstractFactory { /* 美國實作 */ }
// 新增 JapaneseFactory 只需新增類別,零修改既有代碼!

抽象工廠最終結構

配置檔驅動切換




    


// 客戶端零硬編碼
var factory = AbstractFactory.GetInstance();
var bonus = factory.CreateBonus().Calculate();
var tax = factory.CreateTax().Calculate();
Console.WriteLine($"Salary: {4000 + bonus - tax}");

新增日本支援:只需加 JapaneseFactory 類別 + 修改配置檔,完全符合開放封閉原則。

.NET Framework 核心抽象工廠應用

1. ADO.NET DbProviderFactory:教科書級實現

  • AbstractFactory:DbProviderFactory
  • ConcreteFactory:SqlClientFactory、OracleClientFactory、OleDbFactory、OdbcFactory
  • Product Family:Connection、Command、Parameter、DataAdapter、CommandBuilder、DataSourceEnumerator

DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
using (var conn = factory.CreateConnection()) { conn.ConnectionString = "..."; conn.Open(); }
using (var cmd = factory.CreateCommand()) { cmd.Connection = conn; cmd.CommandText = "SELECT * FROM Users"; }
using (var adapter = factory.CreateDataAdapter()) { adapter.SelectCommand = cmd; adapter.Fill(dataSet); }

應用程式完全脫離具體資料庫類型,僅依賴 DbProviderFactory 抽象介面。

2. ASP.NET Control 建構:ControlBuilder 體系

  • 頁面解析器根據標籤前綴(asp:、custom:)選擇對應的 ControlBuilder 工廠
  • 每個 Builder 知悉如何建構特定控制項樹(產品族群)

抽象工廠的關鍵設計決策

產品創建實現方式

  1. 工廠方法:每個產品一個虛擬方法(標準做法,如 DbProviderFactory)
  2. 原型模式:工廠持有原型實例,創建時 Clone()(適合產品實例化昂貴、狀態複雜)
  3. 單例工廠:每個 ConcreteFactory 通常實作為單例,全域唯一存取點

擴展新產品類型的痛點

抽象工廠最大弱點:難以支援「新產品類型」。若需新增 IReport 產品,必須:

  1. 修改 AbstractFactory 加入 CreateReport()
  2. 修改所有 ConcreteFactory 實作新方法

李建忠老師指出:「對於新系列加新對象,目前還沒有完美的做法,這種變化實在太劇烈了」。緩解策略:參數化工廠方法 CreateProduct(ProductType type),但犧牲型別安全。

適用場景判斷清單

以下情況適用抽象工廠:

  • 系統不應依賴產品創建、組合、表示細節
  • 系統有多個產品族,一次只消費其中一族
  • 同族產品必須協同使用(一致性約束)
  • 提供產品類庫,所有產品以相同介面出現,客戶端不依賴實現

優缺點總結

優點缺點
分離具體類別,客戶端零硬編碼難以擴展新產品類型(需改介面與所有工廠)
易於切換產品族(單點修改/配置)介面膨脹:產品類型多時 AbstractFactory 方法過多
強制產品族一致性(避免混搭)複雜度較高:需維護雙重平行階層
利於團隊分工(介面契約為界)過度設計風險:單一產品族無需此模式

總結

抽象工廠模式是「面向介面編程」在物件創建層面的極致體現。它不創建單一物件,而是創建「經過驗證、相互匹配的物件家族」。從 ADO.NET Provider 到跨平台 UI 庫、從雲端資源佈建到遊戲場景風格系統,抽象工廠無處不在。掌握它,意味著你理解了如何用「配置驅動實作選擇」取代「硬編碼綁定」,這是構建可擴展、可維護、可部署企業級系統的核心能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved