一、簡單工廠模式:
簡單工廠模式是工廠模式中最簡單的一種,他可以用比較簡單的方式隱藏創建對象的細節,一般只需要告訴工廠類所需要的類型,工廠類就會返回需要的產品類,但客戶端看到的只是產品的抽象對象,無需關心到底是返回了哪個子類。客戶端唯一需要知道的具體子類就是工廠子類。除了這點,基本是達到了依賴倒轉原則的要求。
假如,我們不用工廠類,只用CreateOperate和它的子類,那客戶端每次使用不同的子類的時候都需要知道到底是用哪一個子類,當類比較少的時候還沒什麼問題,但是當類比較多的時候,管理起來就非常的麻煩了,就必須要做大量的替換,一個不小心就會發生錯誤。而使用了工廠類之後,就不會有這樣的問題,不管裡面多少個類,我只需要知道類型號即可。不過,這裡還有一個疑問,那就是如果我每次用工廠類創建的類型都不相同,這樣修改起來的時候還是會出現問題,還是需要大量的替換。所以簡單工廠模式一般應該於程序中大部分地方都只使用其中一種“產品”,工廠類也不用頻繁創建產品類的情況。這樣修改的時候只需要修改有限的幾個地方即可。
看了許多工廠模式的例子,覺得加減乘除運算工廠模式最能直觀易懂的講解工廠模式,當需要加法類的時候,調用工廠類的CreateOperate(),要指定生產相應的“產品”,見類圖:
#include <iostream> #include <string> using namespace std; class Operation { public: double numberA, numberB; virtual double getResult() { return 0; } }; class addOperation :public Operation { double getResult() { return numberA + numberB; } }; class subOperation :public Operation { double getResult() { return numberA - numberB; } }; class mulOperation :public Operation { double getResult() { return numberA*numberB; } }; class divOperation :public Operation { double getResult() { return numberA / numberB; } }; class operFactory { public: static Operation *createOperation(char c) { switch (c) { case '+': return new addOperation; break; case '-': return new subOperation; break; case '*': return new mulOperation; break; case '/': return new divOperation; break; } } }; int main() { Operation *oper = operFactory::createOperation('+'); //Operation *oper = operFactory::createOperation('-'); //Operation *oper = operFactory::createOperation('*'); //Operation *oper = operFactory::createOperation('/'); oper->numberA = 9; oper->numberB = 99; cout << oper->getResult() << endl; return 0; }
調用工廠,需要createOperator("/"),就能返回除法運算符。
優點:客戶端不需要修改代碼。
缺點: 當需要增加新的運算類的時候,不僅需新加運算類,還要修改工廠類,違反了開閉原則。
二、工廠方法模式:
UML類圖如下:
#include <iostream> #include <string> using namespace std; class Operation { public: double numberA,numberB; virtual double getResult() { return 0; } }; class addOperation:public Operation { double getResult() { return numberA+numberB; } }; class subOperation:public Operation { double getResult() { return numberA-numberB; } }; class mulOperation:public Operation { double getResult() { return numberA*numberB; } }; class divOperation:public Operation { double getResult() { return numberA/numberB; } }; class IFactory { public: virtual Operation *createOperation()=0; }; class AddFactory:public IFactory { public: static Operation *createOperation() { return new addOperation(); } }; class SubFactory:public IFactory { public: static Operation *createOperation() { return new subOperation(); } }; class MulFactory:public IFactory { public: static Operation *createOperation() { return new mulOperation(); } }; class DivFactory:public IFactory { public: static Operation *createOperation() { return new divOperation(); } }; int main() { Operation *oper=MulFactory::createOperation(); oper->numberA=9; oper->numberB=99; cout<<oper->getResult()<<endl; return 0; }
這個和簡單工廠有區別,簡單工廠模式只有一個工廠,工廠方法模式對每一個產品都有相應的工廠
好處:增加一個運算類(例如N次方類),只需要增加運算類和相對應的工廠,兩個類,不需要修改工廠類。
缺點:增加運算類,會修改客戶端代碼,工廠方法只是把簡單工廠的內部邏輯判斷移到了客戶端進行。
以股票行情滬深板塊行情數據訪問為例,行情源訪問程序設計,不同的行情訪問方式可能不一樣,為了抽象對對不同行情的訪問,可以將行情源隱藏起來,提供統一的訪問方式,用多態進行實現。
#include <iostream> #include <string> using namespace std; class Icode { public: virtual void Getcode()=0; virtual void Setcode()=0; }; class ShenAcode:public Icode { public: void Getcode() { cout<<"在ShenA中返回code"<<endl; } void Setcode() { cout<<"在ShenA中設置code"<<endl; } }; class ShangAcode:public Icode { public: void Getcode() { cout<<"在ShangA中返回code"<<endl; } void Setcode() { cout<<"在ShangA中設置code"<<endl; } }; class Iindex { public: virtual void Getindex()=0; virtual void Setindex()=0; }; class ShenAindex:public Iindex { public: void Getindex() { cout<<"在ShenA中返回index"<<endl; } void Setindex() { cout<<"在ShenA中設置index"<<endl; } }; class ShangAindex:public Iindex { public: void Getindex() { cout<<"在ShangA中返回index"<<endl; } void Setindex() { cout<<"在ShangA中設置index"<<endl; } }; class IFactory { public: virtual Icode *CreateCode()=0; virtual Iindex *CreateIndex()=0; }; class ShenAFactory:public IFactory { public: Icode *CreateCode() { return new ShenAcode(); } Iindex *CreateIndex() { return new ShenAindex(); } }; class ShangAFactory:public IFactory { public: Icode *CreateCode() { return new ShangAcode(); } Iindex *CreateIndex() { return new ShangAindex(); } }; /*************************************************************/ class DataShangA { private: static string stock; //string stock="ShangA"; public: static Icode *CreateCode() { if(stock=="ShangA") { return new ShangAcode(); } else if(stock=="ShenA") { return new ShenAcode(); } } static Iindex *CreateIndex() { if(stock=="ShangA") { return new ShangAindex(); } else if(stock=="ShenA") { return new ShenAindex(); } } }; string DataShangA::stock="ShenA"; /*************************************************************/ int main() { //IFactory *factory=new ShenAFactory(); IFactory *factory; Icode *code; Iindex *index; factory=new ShangAFactory(); code=factory->CreateCode(); index=factory->CreateIndex(); code->Getcode(); code->Setcode(); index->Getindex(); index->Setindex(); code=DataShangA::CreateCode(); index=DataShangA::CreateIndex(); code->Getcode(); code->Setcode(); index->Getindex(); index->Setindex(); return 0; }