設計模式 c++版(5)——抽象工廠模式
定義:為建立一組相關或相互依賴的物件提供一個介面,而且無需指定它們的具體類
示例一:女媧造人擴充套件
造出來黑、白、黃種人,分別有性別分類 類圖說明:一個介面,多個抽象類,N個實現類,每個人種都是一個抽象類,性別是在各個實現類中實現的。
1. 結構說明:
HumanFactory 介面,這個介面中定義了三個方法,分別用來產生三個不同膚色的人種FemalFactory 和 MaleFactory 兩個實現類,實現膚色、性別定義AbstractBlackHuman 每個抽象類都有兩個實現類,分別實現公共的、最具體的事物:膚色和語言。
2. 女媧造人類圖9-2:
3. 女媧造人,程式碼清單9-2:
#include <QCoreApplication> #include <QDebug> ////// ********** 1. 女媧造人擴充套件,程式碼清單9-1:***************// class Human { public: virtual void getColor() = 0; virtual void talk() = 0; virtual void getSex() = 0; }; class YellowHuman:public Human { public: virtual void getColor() {qDebug() << "YellowHuman color: yellow";} virtual void talk() {qDebug() << "YellowHuman talk: ccc";} }; class FYellowHuman:public YellowHuman { public: virtual void getSex() {qDebug() << "*FemalYellowHuman*";} }; class HumanFactory { public: virtual Human* createYellowHuman() = 0; }; class FemalFactory:public HumanFactory { public: virtual Human* createYellowHuman() { FYellowHuman *hu = new FYellowHuman(); Human *human = dynamic_cast<Human*>(hu); return human; } }; int main() { FemalFactory factory; Human *human = factory.createYellowHuman(); human->getSex(); human->getColor(); human->talk(); return 0; }
4. 這裡只寫出了製造女性黃種人的示例程式碼,其他類同
示例二:通用抽象工廠模式
1. 抽象工廠模式通用類圖,類圖9-3
說明:抽象工廠模式是工廠模式的升級版本,在有多個業務品種、業務分類時,通過抽象工廠模式產生需要的物件是一種非常好的解決方式。
2. 抽象工廠模式通用原始碼類圖,類圖9-4
說明:有兩個相互影響的產品線(也叫做產品族),例如製造汽車的左側門和右側門,這兩個應該是數量相等的——兩個物件之間的約束,每個型號的車門都是不一樣的,這是產品等級結構約束的。
3. 通用抽象工廠模式,程式碼清單9-2:
#include <QCoreApplication> #include <QDebug> ////// ********** 2.抽象工廠模式的通用原始碼 ,程式碼清單9-1:***************// //ProductA class AbstractProductA { public: void shareMethod(){} virtual void doSomething() = 0; }; class ProductA1:public AbstractProductA { public: virtual void doSomething(){qDebug() << "ProductA1 method";} }; class ProductA2:public AbstractProductA { public: virtual void doSomething(){qDebug() << "ProductA2 method";} }; //ProductB class AbstractProductB { public: void shareMethod(){} virtual void doSomething() = 0; }; class ProductB1:public AbstractProductB { public: virtual void doSomething(){qDebug() << "ProductB1 method";} }; class ProductB2:public AbstractProductB { public: virtual void doSomething(){qDebug() << "ProductB2 method";} }; //Creator class AbstractCreator { public: virtual AbstractProductA* createProductA() = 0; virtual AbstractProductB* createProductB() = 0; }; class Creator1:public AbstractCreator { public: virtual AbstractProductA* createProductA() { ProductA1 *a1 = new ProductA1(); AbstractProductA *product = dynamic_cast<AbstractProductA*>(a1); return product; } virtual AbstractProductB* createProductB() { ProductB1 *b1 = new ProductB1(); AbstractProductB *product = dynamic_cast<AbstractProductB*>(b1); return product; } }; class Creator2:public AbstractCreator { public: virtual AbstractProductA* createProductA() { ProductA2 *a2 = new ProductA2(); AbstractProductA *product = dynamic_cast<AbstractProductA*>(a2); return product; } virtual AbstractProductB* createProductB() { ProductB2 *b2 = new ProductB2(); AbstractProductB *product = dynamic_cast<AbstractProductB*>(b2); return product; } }; int main () { Creator1 creator1; Creator2 creator2; AbstractProductA *a1 = creator1.createProductA(); AbstractProductA *a2 = creator2.createProductA(); AbstractProductB *b1 = creator1.createProductB(); AbstractProductB *b2 = creator2.createProductB(); a1->doSomething(); a2->doSomething(); b1->doSomething(); b2->doSomething(); return 0; }
說明:場景類中,沒有任何一個方法與實現類有關,對於一個產品來說,我們只要知道他的工廠方法就可以直接產生一個產品隊形,無需關心他的實現類。
三、工廠方法模式的應用
優點:
- 封裝性。每個產品的實現類不是高層模組要關心的,它要關心的是介面。只要知道工廠類,就可以創建出一個需要的物件。
- 產品族內的約束為非公開狀態。具體的產品族內的約束是在工廠內實現的
缺點:
產品族擴充套件非常困難。以通用程式碼為例,如果要增加一個產品C,抽象類 AbstractCreator 要增加一個方法 createProductC() ,另外兩個實現類都需要修改,違反了開閉原則。
使用場景:
一個物件族(或是一組沒有任何關係的物件)都有相同的約束,則可以使用抽象工廠模式。 例如:一個文字編輯器和一個圖片處理器,都是軟體實體,但是在*nix 下的文字編輯器和 windows 下的文字編輯器雖然功能和介面都相同,但是程式碼實現不同,圖片處理器也有類似情況。也就具有了共同的約束條件:作業系統型別。於是我們可以使用抽象工廠模式,產生不同作業系統下的編輯器和圖片處理器。
注意事項:
在抽象工廠模式的缺點中,我們提到抽象工廠模式的產品族擴充套件比較困難,但是產品等級容易擴充套件。只要增加一個工廠類負責新增加出來的產品生產任務即可。也就是說橫向擴充套件容易,縱向擴充套件困難。以女媧造人為例,產品登記彙總只有男、女兩個性別,需要再增加雙性人,吶我們需要增加咱哥產品類,分別對應不同的膚色,然後再建立一個工廠類,專門負責不同膚色人的雙性人的建立任務,完全通過擴充套件來實現需求的變更,從這一點上看,抽象工廠模式符合開閉原則。
四、最佳實踐
在軟體產品開發過程中,涉及不同作業系統的時候,都可以考慮使用抽象工廠模式。例如一個應用,需要再三個不同平臺(windows 、linux 、android)上執行,可以通過抽象工廠模式遮蔽掉作業系統對應用的影響。三個不同作業系統上的軟體功能、應用邏輯、UI都應該是非常類似的,唯一不同的是呼叫不同的工廠方法,由不同的產品類去處理與作業系統互動的資訊。
參考文獻《秦小波. 設計模式之禪》(第2版) (華章原創精品) (Kindle 位置 308-310). 機械工業出版社