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

C# 工廠方法模式實戰:延遲實例化與子類別決定建立邏輯

     編輯:關於C#

前言

當系統需要建立物件,但具體建立哪種類別、如何建立由子類別決定時,工廠方法模式提供標準方案:定義一個建立物件的介面(工廠方法),讓子類別決定實例化哪個類別。這將物件建立邏輯從使用者中分離,支援開閉原則——新增產品類別只需新增對應工廠子類別,無需修改既有程式碼。本文以訊息系統為例,展示 SqlMessageFactory/XmlMessageFactory 如何分別建立 SqlMessage/XmlMessage,客戶端透過抽象工廠介面統一使用。

模式結構與四大角色

  • Product(產品介面):AbstractMessage,定義 Get()、Insert() 共同操作。
  • ConcreteProduct(具體產品):SqlMessage、XmlMessage,實作不同儲存邏輯。
  • Creator(抽象建構者):AbstractMessageFactory,宣告工廠方法 CreateMessage(),可包含使用產品的業務邏輯(如 AnOperation())。
  • ConcreteCreator(具體建構者):SqlMessageFactory、XmlMessageFactory,實作工廠方法回傳對應產品實例。
工廠方法模式類別圖

核心程式碼機制深度解析

1. 產品介面與具體產品

public abstract class AbstractMessage
{
    public abstract List<MessageModel> Get();
    public abstract bool Insert(MessageModel mm);
}

public class SqlMessage : AbstractMessage
{
    public override List<MessageModel> Get()
    {
        var l = new List<MessageModel>();
        l.Add(new MessageModel("SQL方式獲取Message", DateTime.Now));
        return l;
    }
    public override bool Insert(MessageModel mm) { return true; }
}

public class XmlMessage : AbstractMessage
{
    public override List<MessageModel> Get()
    {
        var l = new List<MessageModel>();
        l.Add(new MessageModel("XML方式獲取Message", DateTime.Now));
        return l;
    }
    public override bool Insert(MessageModel mm) { return true; }
}

2. 抽象建構者:工廠方法宣告

public abstract class AbstractMessageFactory
{
    public abstract AbstractMessage CreateMessage(); // 工廠方法

    // 可選:使用產品的業務邏輯(模板方法風格)
    public void AnOperation()
    {
        var product = CreateMessage();
        // 使用 product...
    }
}

3. 具體建構者:實作工廠方法

public class SqlMessageFactory : AbstractMessageFactory
{
    public override AbstractMessage CreateMessage() => new SqlMessage();
}

public class XmlMessageFactory : AbstractMessageFactory
{
    public override AbstractMessage CreateMessage() => new XmlMessage();
}

關鍵:每個具體建構者只負責建立一種具體產品,建立邏輯封裝在工廠方法中。

4. 客戶端:面向抽象建構者程式設計


AbstractMessageFactory amf = new SqlMessageFactory(); // 選擇具體工廠
AbstractMessage am = amf.CreateMessage();             // 建立產品
Response.Write(am.Insert(new MessageModel("插入", Now)));
Response.Write(am.Get()[0].Message);

amf = new XmlMessageFactory(); // 切換工廠
am = amf.CreateMessage();
Response.Write(am.Insert(new MessageModel("插入", Now)));
Response.Write(am.Get()[0].Message);

執行結果驗證


True
SQL方式獲取Message 2007-5-4 22:34:39
True
XML方式獲取Message 2007-5-4 22:34:39

客戶端程式碼僅依賴 AbstractMessageFactory 與 AbstractMessage 介面,切換工廠即切換產品系列,零修改業務邏輯。

工廠方法模式 vs 簡單工廠 vs 抽象工廠

模式核心機制適用場景擴展方式
簡單工廠單一類別含 switch 建立邏輯產品類別固定、少量、客戶端不關心建立細節修改工廠類別 (違反開閉)
工廠方法抽象建構者 + 具體建構者階層產品類別可擴展、建立邏輯複雜、需支援多種產品系列新增建構者子類別 (符合開閉)
抽象工廠建構者介面定義多個工廠方法 (產品族)需建立相關/相依的產品族 (如:SQL 連線+命令+讀取器)新增建構者子類別實作整族產品

進階應用與最佳實務

參數化工廠方法

工廠方法接受參數決定建立哪種子類型:


public abstract class MessageFactory
{
    public abstract AbstractMessage CreateMessage(string type); // "sql" | "xml"
}

public class UnifiedMessageFactory : MessageFactory
{
    public override AbstractMessage CreateMessage(string type)
    {
        return type switch { "sql" => new SqlMessage(), "xml" => new XmlMessage(), _ => throw new ArgumentException() };
    }
}

優點:減少建構者類別數量。缺點:引入條件判斷、違反開閉原則(新增類型需修改 switch)。

工廠方法與依賴注入結合


// 註冊
services.AddTransient();
// 或多實現
services.AddKeyedTransient("sql");
services.AddKeyedTransient("xml");

// 客戶端注入
public class MessageService
{
    private readonly AbstractMessageFactory _factory;
    public MessageService(AbstractMessageFactory factory) => _factory = factory;
    public void Process() => _factory.CreateMessage().Insert(...);
}

工廠方法在框架中的應用:模板方法搭檔

Creator 中定義 AnOperation() 呼叫 CreateMessage(),子類別只需實作工廠方法即可客製化演算法中的物件建立步驟。這是「框架設計」核心技巧:框架定義骨架(AnOperation),應用提供具體化(CreateMessage)。

.NET 實際應用案例

  • ADO.NET:DbProviderFactory (Creator) → SqlClientFactory (ConcreteCreator) → CreateConnection/Command/Parameter (Factory Methods)。
  • ASP.NET Core:IControllerFactory → DefaultControllerFactory → CreateController。
  • Entity Framework:IDbContextFactory → PooledDbContextFactory → CreateDbContext。
  • HttpClientFactory:IHttpClientFactory → DefaultHttpClientFactory → CreateClient。
  • Logging:ILoggerFactory → LoggerFactory → CreateLogger。

優缺點總結

優點

  • 解耦建立與使用:客戶端不知曉具體產品類別。
  • 符合開閉原則:新增產品只需新增建構者子類別。
  • 單一職責:建立邏輯集中在建構者,不分散在客戶端。
  • 支援多型建立:同一建構者介面可建立不同產品階層。

缺點

  • 類別數量成雙增長:每個產品需對應一個建構者(可用參數化工廠/反射緩解)。
  • 客戶端需知曉具體建構者類別(除非配合 DI/簡單工廠)。
  • 若產品建立邏輯極簡,可能過度設計(YAGNI)。

適用性判斷

  • 類別預先不知道要建立哪種物件?
  • 類別希望由子類別指定建立的物件?
  • 類別將建立職責委派給多個輔助子類別,並希望將哪個輔助子類別是代理者這項資訊局部化?

總結

工廠方法模式以「虛擬建構子」將物件實例化延遲至子類別,實現「建立與使用分離」與「開閉原則」。本範例以 SqlMessageFactory/XmlMessageFactory 分別建立 SqlMessage/XmlMessage 為例,完整展示了產品介面、具體產品、抽象建構者、具體建構者四角色協作,驗證了客戶端面向抽象介面程式設計、切換工廠即切換產品系列的核心優勢。實務中,從 ADO.NET Provider、Controller Factory、DbContext Factory 到 HttpClient Factory、Logger Factory,工廠方法模式是框架庫、中間件、可擴展系統實現「多型建立、插件化架構」的基石。掌握其核心——「Creator 定義工廠方法、ConcreteCreator 實作建立邏輯、Client 依賴 Creator 介面」、與簡單工廠/抽象工廠的區別、DI 容器整合現代寫法,能讓你在設計需要「彈性建立、多實現切換、框架可擴展」的系統時,構建出清晰分層、低耦合、高擴展性的物件建立架構。


參考資源:DoFactory Factory Method Pattern

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