本章介紹 FACTORY 模式,說明如何在遵守 DIP(依賴反轉原則)的前提下建立具體類別的實例。FACTORY 模式讓高層策略模組不需要知道具體實作類別,同時保持建立物件的能力。
問題:DIP 與物件建立的矛盾#
- DIP 告訴我們高層模組不應依賴低層模組,兩者都應依賴抽象
- 但建立物件時,我們必須呼叫具體類別的建構子——這直接違反了 DIP
- FACTORY 模式就是為了解決這個矛盾:將物件建立的邏輯隔離到一個獨立的類別中
FACTORY 的基本結構#

Figure 29.2: Application of FACTORY to SomeApp
- 定義一個抽象的 Factory 介面,宣告建立物件的方法(回傳抽象型別)
- 具體的 Factory 實作類別負責
new出具體物件 - 應用程式依賴抽象的 Factory 介面,而非具體的 Factory 實作
public interface ShapeFactory
{
Shape MakeSquare();
Shape MakeCircle();
}
public class ShapeFactoryImplementation : ShapeFactory
{
public Shape MakeSquare() { return new Square(); }
public Shape MakeCircle() { return new Circle(); }
}可替換的工廠(Substitutable Factories)#

Figure 29.3: Substitutable factory
- 由於應用程式只依賴 Factory 介面,可以在不同情境下替換不同的 Factory 實作
- 典型場景:測試時使用測試用的 Factory,正式環境使用真實的 Factory
- 這讓整個系統的具體實作可以在啟動時(或測試時)一次性替換
在薪資系統中的應用#

Figure 29.4: Payroll uses database
- 薪資系統的
TransactionApplication需要使用PayrollDatabase,但不應直接依賴SqlPayrollDatabase - 解法:建立
PayrollDatabase介面與對應的PayrollDatabaseFactory

Figure 29.6: Spoofing the factory
- 測試時可以用假的 Factory(Spoof) 來替換真實的資料庫實作,注入一個記憶體版本的
PayrollDatabase - 這避免了測試對真實資料庫的依賴,大幅加速測試執行
重點: FACTORY 模式的核心價值不僅是封裝建立邏輯,更是維護 DIP 的完整性。透過 FACTORY,高層模組可以在完全不知道具體類別的情況下建立物件。
初始化問題#
- 如果所有具體實作都隱藏在 Factory 後面,那麼誰來建立 Factory 本身?
- 答案是系統的
main函式或啟動程序:它是整個系統中唯一「知道所有具體類別」的地方 main建立具體的 Factory 實作,並將其注入到需要的模組中
技巧: FACTORY 模式通常與 SINGLETON 或靜態方法搭配使用,讓 Factory 的實例在全系統中可存取。但要注意不要讓這種全域存取點破壞了可測試性。
本章小結#
FACTORY 模式是 DIP 的必要搭配——它讓我們在遵守「依賴抽象」的原則下,仍能建立具體物件。透過可替換的 Factory,系統的具體實作可以在測試與正式環境之間無縫切換。