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

.NET 設計模式(5):工廠方法模式——延遲實例化決策的靈活製造術

     編輯:關於.NET

前言:封裝「創建什麼」的變化

直接 new ConcreteClass() 將客戶端與具體實現強綁定。工廠方法模式(Factory Method Pattern)的核心思想:定義一個創建物件的介面,讓子類別決定實例化哪一個類別。Factory Method 使一個類別的實例化延遲到其子類別(GoF)。它不創建物件,而是「委託」創建——這一層間接,正是應對變化的關鍵。

從 Switch 案例看演進必要性


// 反模式:集中式 switch,違反開放封閉原則
public class Log {
    public void Write(string logType) {
        switch (logType.ToLower()) {
            case "event": WriteEvent(); break;
            case "file": WriteFile(); break;
            case "database": WriteDatabase(); break; // 新增需修改此處
        }
    }
}

問題:每新增一種日誌方式,就要修改 Log 類別,引入測試風險,違反單一職責。

工廠方法重構步驟

1. 提煉產品介面與具體實作


public abstract class Log { public abstract void Write(); }
public class EventLog : Log { public override void Write() => Console.WriteLine("EventLog"); }
public class FileLog : Log { public override void Write() => Console.WriteLine("FileLog"); }
public class DatabaseLog : Log { public override void Write() => Console.WriteLine("DatabaseLog"); }

產品階層

2. 引入工廠介面與具體工廠(平行階層)


public abstract class LogFactory { public abstract Log Create(); }
public class EventLogFactory : LogFactory { public override Log Create() => new EventLog(); }
public class FileLogFactory : LogFactory { public override Log Create() => new FileLog(); }
public class DatabaseLogFactory : LogFactory { public override Log Create() => new DatabaseLog(); }

工廠平行階層

3. 客戶端面向抽象工廠編程


public class App {
    public static void Main() {
        // 僅此處綁定具體工廠,其餘程式碼零修改
        LogFactory factory = new EventLogFactory(); 
        // 或從配置檔讀取:factory = CreateFactoryFromConfig();
        
        Log log = factory.Create();
        log.Write();
    }
}

切換實作僅需修改一行:factory = new FileLogFactory();。搭配配置檔 + 反射,可達到零程式碼修改切換:


// App.config


// 客戶端
string factoryName = ConfigurationManager.AppSettings["factoryName"];
LogFactory factory = (LogFactory)Assembly.Load("MyAssembly").CreateInstance(factoryName);

ASP.NET 管線中的經典應用:IHttpHandlerFactory

ASP.NET 處理請求的核心管線大量使用工廠方法:

  1. HttpRuntime 接收請求,建立 HttpContext
  2. 呼叫 HttpApplicationFactory.GetApplicationInstance() 取得 HttpApplication(工廠方法)
  3. HttpApplication 根據副檔名從 <httpHandlers> 區段解析對應的 IHttpHandlerFactory
  4. 呼叫 factory.GetHandler(context, ...) 取得具體 IHttpHandler(如 PageHandlerFactory 產生 .aspx 處理器)

HttpApplicationFactory 結構

PageHandlerFactory 產生處理器

自訂處理器範例


// 1. 實作介面
public class MyHandlerFactory : IHttpHandlerFactory {
    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) 
        => new MyHandler();
    public void ReleaseHandler(IHttpHandler handler) { }
}
public class MyHandler : IHttpHandler {
    public void ProcessRequest(HttpContext context) => context.Response.Write("Custom handler!");
    public bool IsReusable => false;
}

// 2. Web.config 註冊

    


// 3. IIS 映射 *.myext 到 aspnet_isapi.dll

這展示了工廠方法支援「框架定義介面、應用程式提供實作、配置檔連結雙方」的擴展性架構。

.NET Framework 內建工廠方法圖譜

  • WebRequest.Create(uri):根據 URI Scheme 回傳 HttpWebRequest、FtpWebRequest、FileWebRequest
  • SymmetricAlgorithm.Create() / HashAlgorithm.Create():根據配置/演算法名稱回傳對應加密實作
  • DbProviderFactory:ADO.NET 統一存取模型的核心工廠
  • IEnumerable.GetEnumerator():集合與迭代器的工廠方法關係
  • Activator.CreateInstance():通用反射工廠

工廠方法的兩種形式與進階技巧

形式特徵適用場景
抽象 CreatorCreator 為 abstract,不提供預設實作強制子類別實作、框架設計
具體 CreatorCreator 為 concrete,提供預設工廠方法實作應用層、允許覆寫預設行為

參數化工廠方法


public abstract class LogFactory {
    public virtual Log Create(LogType type) { // 參數化,單一工廠支援多產品
        switch (type) {
            case LogType.Event: return new EventLog();
            case LogType.File: return new FileLog();
        }
        throw new ArgumentException();
    }
}

參數化工廠方法減少具體工廠類別數量,但引入 switch——需在「類別數量」與「條件邏輯」間權衡。

工廠方法不只是創建

工廠方法內可執行:參數驗證、預設值設定、相依服務注入、快取檢查、生命週期管理(如單例檢查)、記錄審計日誌等。這使其比單純 new 強大得多。

適用場景與決策指南

以下情況適用工廠方法:

  1. 類別預先不知需創建哪種具體物件
  2. 類別希望由子類別指定創建的物件
  3. 將創建職責委託給多個輔助子類別之一,並將代理資訊局部化
  4. 需要從配置檔、資料庫、服務發現動態決定具體實作

常見誤區與避坑指南

  • 過度設計:只有單一固定實作時,直接 new 即可,無需工廠
  • 工廠即服務定位器:工廠方法應專注創建,複雜相依解析交給 DI 容器
  • 靜態工廠方法 vs 工廠方法模式:LogFactory.Create() 為靜態方法非模式;模式強調「虛擬方法可被子類別覆寫」
  • 忽略參數傳遞:建構子需參數時,工廠方法簽名應包含參數或使用 Builder 輔助

總結

工廠方法模式是設計模式中應用最廣、變體最多的模式。它以「虛擬建構子」之姿,將「實例化決策」從使用者手中收回,交給專門的工廠階層管理。在 .NET 生態中,從 WebRequest 到 ADO.NET Provider、從 ASP.NET 管線到 DI 容器內部,工廠方法無處不在。掌握它,意味著你學會了「延遲綁定」這一應對變化的核心技巧——不在編譯期鎖定具體類別,而在運行期由配置、上下文、策略動態決定。

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