工廠方法模式(Factory Method Pattern)又稱工廠模式,也叫虛擬構造器(Virtual Constructor)模式或者多態工廠(Polymorphic Factory)模式,在工廠方法模式中,工廠父類負責定義建立產品對象的公共接口,而工廠子類則負責生成具體的產品對象,這樣作的目的是將產品類的實例化操做延遲到工廠子類中完成,即經過工廠子類來肯定究竟應該實例化哪個具體產品類。
工廠方法,能夠理解爲一種將實例化邏輯委託給子類的方法,父基類提供共有實現,派生類完成個性化定製實現ios
若是有這樣的場景,存在部分共有的功能邏輯,可是在運行時又須要動態決定使用哪一個子類的邏輯實現,也就是說
須要動態根據需求選擇不一樣的子類實現,這個時候可使用工廠方法。
建議在如下狀況下選用工廠方法模式。c++
初接觸工廠方法模式,會感受,「這不是跟簡單工廠同樣嗎」golang
從本質上講,他們確實是很是相似的,在具體實現上都是「選擇實現」。可是也存在不一樣點,簡單工廠是直接在工廠類裏進行「選擇實現」;而工廠方法會把這個工做延遲到子類來實現,工廠類裏面使用工廠方法的地方是依賴於抽象而不是具體的實現,從而使得系統更加靈活,具備更好的可維護性和可擴展性。shell
從某個角度講,能夠認爲簡單工廠就是工廠方法模式的一種特例,所以他們的本質是相似的。ide
具體的舉例,簡單工廠實例中,客戶就是要一個門,而不關心建立過程,最後實際創造的是一個木門,這個比較尷尬,若是客戶要的是個鐵門呢?因此在這個例子中,也是存在兩維抽象的,一是「門」這個類型的抽象,二是「造門」這個方法的抽象。簡單工廠只作到了前者,而沒有給出後者的解決方案,若是看咱們按照工廠方法的思路,將門工廠造門這件事進行細分,木門交給木門工廠,鐵門交給鐵門工廠,這就是工廠方法的實現,客戶須要先制定委託對象,而沒必要關係具體怎麼造門。函數
#include <iostream> class IInterviewer { public: virtual void askQuestions() = 0; }; class Developer : public IInterviewer { public: void askQuestions() override { std::cout << "Asking about design patterns!" << std::endl; } }; class CommunityExecutive : public IInterviewer { public: void askQuestions() override { std::cout << "Asking about community building!" << std::endl; } }; class HiringManager { public: void takeInterview() { IInterviewer* interviewer = this->makeInterviewer(); interviewer->askQuestions(); } protected: virtual IInterviewer* makeInterviewer() = 0; }; template <typename Interviewer> class OtherManager : public HiringManager { protected: IInterviewer* makeInterviewer() override { return new Interviewer(); } }; int main() { HiringManager* devManager = new OtherManager<Developer>(); devManager->takeInterview(); HiringManager* marketingMnager = new OtherManager<CommunityExecutive>(); marketingMnager->takeInterview(); return 0; }
運行結果測試
g++ -o factory-method factory-method.cpp --std=c++11 ./factory-method Asking about design patterns! Asking about community building!
IInterviwer爲基礎類,定義爲一個虛基類,具體派生出了Devoloper和CommunityExecutive兩個實現子類;
HiringManager爲工廠基類,定義爲一個虛基類,OtherManager爲具體實現的派生類,根據傳入的template type,返回不一樣的建立對象。優化
package factory_method //Operator是被封裝的接口 type Operator interface { SetA(int) SetB(int) Result() int } //工廠接口 type OperatorFactory interface { Create() Operator } //OperatorBase是Operator接口實現的基類,封裝公有方法 type OperatorBase struct { a,b int } //SetA方法實現 func (op *OperatorBase) SetA(aValue int) { op.a = aValue } //SetB方法實現 func (op *OperatorBase) SetB(bValue int) { op.b = bValue } //下面是分別構造不一樣類型Operator以及對應生產的工廠類 //加法工廠類 type PlusOperatorFactory struct { } //加法工廠類實現工廠接口 func (pof PlusOperatorFactory) Create() Operator { return &PlusOperator{} } //加法類 type PlusOperator struct { OperatorBase } //加法類實現Operator接口的Result函數 func (pop *PlusOperator) Result() int { return pop.a + pop.b } //減法工廠類 type MinusOperatorFactory struct { } //減法工廠類實現工廠接口 func (mof MinusOperatorFactory) Create() Operator { return &MinusOperator{} } //減法類 type MinusOperator struct { OperatorBase } //減法類實現Operator接口的Result函數 func (mop *MinusOperator) Result() int { return mop.a - mop.b }
測試用例ui
package factory_method import "testing" func TestPlusOperator_Result(t *testing.T) { pof := PlusOperatorFactory{} pop := pof.Create() pop.SetA(1) pop.SetB(2) if pop.Result() != 3 { t.Fatal("test plus operator factory failed") } } func TestMinusOperator_Result(t *testing.T) { mof := MinusOperatorFactory{} mop := mof.Create() mop.SetA(2) mop.SetB(1) if mop.Result() != 1 { t.Fatal("test minus operator factory failed") } }
運行結果this
go test -v factory-method.go factory-method_test.go === RUN TestPlusOperator_Result --- PASS: TestPlusOperator_Result (0.00s) === RUN TestMinusOperator_Result --- PASS: TestMinusOperator_Result (0.00s) PASS ok command-line-arguments 0.734s
優化後更實用的版本
func LoadFactory(name string) OperatorFactory { switch name { case "plus": return PlusOperatorFactory{} case "minus": return MinusOperatorFactory{} default: return PlusOperatorFactory{} } }
測試用例
...... pof := LoadFactory("plus") ......