簡單原廠模式:專門定義一個類來負責建立其他類的執行個體,被建立的執行個體通常都具有共同的父類。它又稱為靜態Factory 方法模式,屬於類的建立型模式。
簡單原廠模式的實質是由一個工廠類根據傳入的參數,動態決定應該建立哪一個產品類(這些產品類繼承自一個父類或介面)的執行個體。
意圖:提供一個類,由它負責根據一定的條件建立某一具體類的執行個體
角色及其職責:
- 工廠(Creator)角色:簡單原廠模式的核心,它負責實現建立所有執行個體的內部邏輯。工廠類可以被外界直接調用,建立所需的產品對象。
- 抽象(Product)角色:簡單原廠模式所建立的所有對象的父類,它負責描述所有執行個體所共有的公用介面。
- 具體產品(Concrete Product)角色:簡單原廠模式的建立目標,所有建立的對象都是充當這個角色的某個具體類的執行個體。一般來講它是抽象產品類的子類,實現了抽象產品類中定義的所有介面方法。
模式的特點:
- 優點:簡單原廠模式的建立目標,所有建立的對象都是充當這個角色的某個具體類的執行個體。在這個模式中,工廠類是整個模式的關鍵所在。它包含必要的判斷邏輯,能夠根據外界給定的資訊,決定究竟應該建立哪個具體類的對象。使用者在使用時可以直接根據工廠類去建立所需的執行個體,而無需瞭解這些對象是如何建立以及如何組織的。有利於整個軟體體繫結構的最佳化。
- 缺點:體現在其工廠類上,由於工廠類集中了所有執行個體的建立邏輯,所以"高內聚"方面做的並不好。另外,當系統中的具體產品類不斷增多時,可能會出現要求工廠類也要做相應的修改,擴充性並不很好。
Factory 方法模式: Factory 方法模式的對簡單原廠模式進行了抽象。有一個抽象的Factory類(可以是抽象類別和介面),這個類將不在負責具體的產品生產,而是只制定一些規範,具體的生產工作推延到其子類去完成。
意圖:定義一個使用者建立對象的介面,讓子類決定執行個體化哪一個類,Factory 方法模式使一個類的執行個體化延遲到其子類。
優點:實現了開閉原則,可以在不改變工廠的前提下增加新產品。
實現要點:
- Factory Method模式的兩種情況:一是Creator類是一個抽象類別且它不提供它所聲明的Factory 方法的實現;二是Creator是一個具體的類且它提供一個Factory 方法的預設實現。
- Factory 方法是可以帶參數的。
- 工廠的作用並不僅僅只是建立一個對象,它還可以做對象的初始化,參數的設定等。
效果:
- 用Factory 方法在一個類的內部建立對象通常比直接建立對象更靈活。
- Factory Method模式通過物件導向的手法,將所要建立的具體對象的建立工作延遲到了子類,從而提供了一種擴充的策略,較好的解決了這種緊耦合的關係。
適用性:
- 當一個類不知道它所必須建立的對象的類的時候。
- 當一個類希望由它的子類來指定它所建立的對象的時候。
- 當類將建立對象的職責委託給多個協助子類中的某一個,並且你希望將哪一個協助子類是代理者這一資訊局部化的時候。
附註:
- 基類是一個抽象類別,模式必須返回一個完整的可工作的類
- 基類包含預設方法,除非這些預設方法不能勝任才調用子類方法
- 可以講參數傳遞給工廠,告訴工廠返回哪一個類。
抽象原廠模式:提供建立對象的介面。與Factory 方法類似,但此處返回的一系列相關產品。實現過程同樣推延到子系列類去實現。與Factory 方法的區別在於他們的層次模型。Factory 方法的抽象基類只有兒子,而抽象原廠模式卻是有孫子,而且每個兒子的兒子們之間有相互關聯依賴關係。
意圖:提供一個建立一系列相關或相互依賴對象的介面,而無需指定它們具體的類。
角色及職責:
- 抽象工廠(Abstract Factory):聲明產生一系列抽象產品的方法
- 具體工廠(Concrete Factory):執行產生一系列抽象產品的方法,產生一系列具體的產品
- 抽象產品(Abstract Product):為這一系列的某一種產品聲明介面
- 具體產品(Product):定義具體工廠產生的具體產品的對象,實現產品介面
- 客戶(Client):我們的應用程式用戶端(不要理解成人),使用抽象產品和抽象工廠產生對象。
附註:簡單工廠、Factory 方法、抽象工廠比較
簡單工廠,Factory 方法,抽象工廠都屬於設計模式中的建立型模式。其主要功能都是協助我們把對象的執行個體化部分抽取了出來,最佳化了系統的架構,並且增強了系統的擴充性。
- 簡單工廠:簡單原廠模式的工廠類一般是使用靜態方法,通過接收的參數的不同來返回不同的對象執行個體。不修改代碼的話,是無法擴充的。
- Factory 方法:Factory 方法是針對每一種產品提供一個工廠類。通過不同的工廠執行個體來建立不同的產品執行個體。在同一等級結構中,支援增加任意產品。
- 抽象工廠:抽象工廠是應對產品族概念的。比如說,每個汽車公司可能要同時生產轎車,貨車,客車,那麼每一個工廠都要有建立轎車,貨車和客車的方法。應對產品族概念而生,增加新的產品線很容易,但是無法增加新的產品。
小結:
- 原廠模式中,重要的是工廠類,而不是產品類。產品類可以是多種形式,多層繼承或者是單個類都是可以的。但要明確的,原廠模式的介面只會返回一種類型的執行個體,這是在設計產品類的時候需要注意的,最好是有父類或者共同實現的介面。使用原廠模式,返回的執行個體一定是工廠建立的,而不是從其他對象中擷取的。原廠模式返回的執行個體可以不是新建立的,返回由工廠建立好的執行個體也是可以的。
區別:
- 簡單工廠 : 用來生產同一等級結構中的任意產品。(對於增加新的產品,無能為力)
- 原廠模式 :用來生產同一等級結構中的固定產品。(支援增加任意產品)
- 抽象工廠:用來生產不同產品族的全部產品。(對於增加新的產品,無能為力;支援增加產品族)
以上三種Factory 方法在等級結構和產品族這兩個方向上的支援程度不同。所以要根據情況考慮應該使用哪種方法。
轉載自http://www.cnblogs.com/BLoodMaster/archive/2010/03/01/1675856.html,感謝作者的辛勤勞動
如有任何不同的見解,請留言,如果在下還會喘氣,會儘快給您回覆
範例程式碼
待產生類
enum CoreType{coreA = 0, coreB = 1};class CSinglecore{private:CSinglecore();};class CSinglecoreA:public CSinglecore{public:CSinglecoreA();};class CSinglecoreB:public CSinglecore{public:CSinglecoreB();};class CMulticore{private:CMulticore();};class CMulticoreA:public CMulticore{public:CMulticoreA();};class CMulticoreB:public CMulticore{public:CMulticoreB();};
簡單原廠模式
class CFactory{public:CSinglecore* CreateSinglecore(CoreType type){CSinglecore* pCore = NULL;if (type == CoreType::coreA)pCore = new CSinglecoreA;else if (type == CoreType::coreB)pCore = new CSinglecoreB;}};
原廠模式
class CFactory{public:virtual CSinglecore* CreateSinglecore() = 0;};class CFactoryA:public CFactory{public:virtual CSinglecore* CreateSinglecore(){CSinglecore* pCore = new CSinglecoreA;return pCore;}};class CFactoryB:public CFactory{public:virtual CSinglecore* CreateSinglecore(){CSinglecore* pCore = new CSinglecoreB;return pCore;}};
抽象原廠模式
class CFactory{public:virtual CSinglecore* CreateSinglecore() = 0;virtual CMulticore* CreateMulticore() = 0;};class CFactoryA:public CFactory{public:virtual CSinglecore* CreateSinglecore(){CSinglecore* pCore = new CSinglecoreA;return pCore;}virtual CMulticore* CreateMulticore(){CMulticore* pCore = new CMulticoreA;return pCore;}};class CFactoryB:public CFactory{public:virtual CSinglecore* CreateSinglecore(){CSinglecore* pCore = new CSinglecoreB;return pCore;}virtual CMulticore* CreateMulticore(){CMulticore* pCore = new CMulticoreB;return pCore;}};