3种工厂模式详解
1、工廠方法模式
1.1、簡單工廠模式
定義:定義了一個創建對象的類,由這個類來封裝實例化對象的行為。
舉例:(我們舉一個水果工廠的例子)
水果工廠一共生產三種類型的水果:apple,pear,banana。通過工廠類(Factory)實例化這三種類型的對象。類圖如下:
#include<iostream> using namespace std; class Produce;//聲明產品類 class Factory//工廠類 { public:Factory() {}~Factory() {}virtual Produce* create_produce(string class_name, string name) = 0;//工廠生產產品,這里的純虛函數是為了讓子工廠生產產品//返回的是一個產品類指針,這就代表了一個產品//這里的name參數是為了返回想要的產品qwq }; class Produce { public:Produce() {}~Produce() {}virtual void show_myname() = 0;//這里定義的純虛函數是為了讓派生類去實現這個函數,有純虛函數的類是抽象類 }; //現在我要開始創建具體的產品了 class Apple :public Produce//這是一個具體的蘋果類 { private:string name; public:Apple(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數 {cout << "我的名稱是:" << name << endl;} }; class Pear :public Produce//這是一個具體的梨類 { private:string name; public:Pear(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數{cout << "我的名稱是:" << name << endl;} }; class Badfruits :public Produce//這是一個具體的壞水果類 { private:string name; public:Badfruits() {}virtual void show_myname()//重寫父類函數{cout << "此產品已經過期!!" << endl;} }; //下面開始創建具體的工廠類 class Factory_fruits :public Factory//這是個水果工廠類 { public:Factory_fruits() {}~Factory_fruits() {}virtual Produce* create_produce(string class_name, string name){if (class_name == "apple"){Produce* my_produce = new Apple(name);//創建name的apple產品 return my_produce;}else if (class_name == "pear"){Produce* my_produce = new Pear(name);//創建name的pear產品return my_produce;}else{Produce* my_produce = new Badfruits();//創建name的pear產品return my_produce;}} }; //初期的搭建工作已經完成,總結一下,我們搭建了兩個抽象類:工廠類,產品類;//產品派生類:蘋果類,梨類,壞水果類//工廠派生類:水果工廠類。//現在我們要用這些東西了 int main() {Factory* my_factory_fruits = new Factory_fruits();//創建一個抽象工廠對象"升級"為水果工廠//這里的"升級"是我的理解 ,事實上是類型轉換 Produce* my_produce_apple = my_factory_fruits->create_produce("apple", "紅富士");//創建抽象產品對象,"升級"為水果工廠加工出來的apple,紅富士 Produce* my_produce_pear = my_factory_fruits->create_produce("pear", "冰糖雪梨");//創建抽象產品對象,"升級"為水果工廠加工出來的pear,冰糖雪梨Produce* my_produce_banana = my_factory_fruits->create_produce("banana", "大香蕉");//創建抽象產品對象,"升級"為水果工廠加工出來的banana,大香蕉,但是工廠不能生產banana,所以只能生產badfruit壞水果 my_produce_apple->show_myname();//產品顯示自己的名稱 my_produce_pear->show_myname();//產品顯示自己的名稱my_produce_banana->show_myname();//產品顯示自己的名稱//下面是銷毀內存delete my_factory_fruits;my_factory_fruits = nullptr;delete my_produce_apple;my_produce_apple = nullptr;delete my_produce_pear;my_produce_pear = nullptr;delete my_produce_banana;my_produce_banana = nullptr;return 0; }??
這種簡單工廠模式有一個很大的缺陷,顧名思義工廠模式,并沒有那么簡單>_<.他不是像簡單工廠那樣一個水果工廠可以生產各種水果,而是一種工廠生產一種水果。就比如蘋果工廠生產蘋果,梨子工廠生產梨子。這樣分開的好處是什么呢???
我看了很多博客,他們都提到了 開放-封閉原則,用自己的話來說,就是如果你想增加新香蕉的產品的話。用簡單工廠模式需要增加一個香蕉類,然后在水果工廠里面增加分支。用工廠模式的話需要增加一個香蕉類和一個香蕉類工廠。。。
但是我們老師經常教導我們,不要改源碼!!!如果用的是簡單工廠模式就必須改源碼中的條件分支,這會被老師罵死的qwq。所以用工廠模式就不用改源碼,只用增加代碼即可。
1.2、工廠模式
#include<iostream> using namespace std; class Produce;//聲明產品類 class Factory//工廠類 { public:Factory() {}~Factory() {}virtual Produce* create_produce(string name) = 0;//工廠生產產品,這里的純虛函數是為了讓子工廠生產產品//返回的是一個產品類指針,這就代表了一個產品//這里的name參數是為了返回想要的產品qwq }; class Produce { public:Produce() {}~Produce() {}virtual void show_myname() = 0;//這里定義的純虛函數是為了讓派生類去實現這個函數,有純虛函數的類是抽象類 }; //現在我要開始創建具體的產品了 class Apple :public Produce//這是一個具體的蘋果類 { private:string name; public:Apple(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數 {cout << "我的名稱是:" << name << endl;} }; class Pear :public Produce//這是一個具體的梨類 { private:string name; public:Pear(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數{cout << "我的名稱是:" << name << endl;} }; class Banana :public Produce//這是一個具體的香蕉類 { private:string name; public:Banana(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數{cout << "我的名稱是:" << name << endl;} }; //下面開始創建具體的工廠類 class Factory_apple :public Factory//這是個水果工廠類 { public:Factory_apple() {}~Factory_apple() {}virtual Produce* create_produce(string name){Produce* my_produce = new Apple(name);//創建name的apple產品 return my_produce;} }; class Factory_pear :public Factory//這是個水果工廠類 { public:Factory_pear() {}~Factory_pear() {}virtual Produce* create_produce(string name){Produce* my_produce = new Pear(name);//創建name的pear產品 return my_produce;} }; class Factory_banana :public Factory//這是香蕉類 { public:Factory_banana() {}~Factory_banana() {}virtual Produce* create_produce(string name){Produce* my_produce = new Banana(name);//創建name的badfruits產品 return my_produce;} }; //初期的搭建工作已經完成,總結一下,我們搭建了兩個抽象類:工廠類,產品類;//產品派生類:蘋果類,梨類,壞水果類//工廠派生類:蘋果工廠類。梨類工廠類。壞水果工廠類 //現在我們要用這些東西了 int main() {Factory* my_factory_apple = new Factory_apple();//創建一個抽象工廠對象"升級"為蘋果工廠//這里的"升級"是我的理解 ,事實上是類型轉換Factory* my_factory_pear = new Factory_pear();//創建一個抽象工廠對象"升級"為梨子工廠Factory* my_factory_banana = new Factory_banana();//創建一個抽象工廠對象"升級"為香蕉工廠Produce* my_produce_apple = my_factory_apple->create_produce("紅富士");//創建抽象產品對象,"升級"為蘋果工廠加工出來的apple,紅富士 Produce* my_produce_pear = my_factory_pear->create_produce("冰糖雪梨");//創建抽象產品對象,"升級"為梨子工廠加工出來的pear,冰糖雪梨Produce* my_produce_banana = my_factory_banana->create_produce("大香蕉");//創建抽象產品對象,"升級"為香蕉工廠加工出來的banana my_produce_apple->show_myname();//產品顯示自己的名稱 my_produce_pear->show_myname();//產品顯示自己的名稱my_produce_banana->show_myname();//產品顯示自己的名稱//下面是銷毀內存delete my_factory_apple;my_factory_apple = nullptr;delete my_factory_pear;my_factory_pear = nullptr;delete my_factory_banana;my_factory_banana = nullptr;delete my_produce_apple;my_produce_apple = nullptr;delete my_produce_pear;my_produce_pear = nullptr;delete my_produce_banana;my_produce_banana = nullptr;return 0; }??
2、抽象工廠模式
顧名思義這個模式比普通的工廠模式抽象一點。
按照我個人的理解,簡單工廠模式,工廠模式,抽象模式主要的差別就在與工廠的分類不同。
簡單工廠模式:一個產品一個工廠,十個產品一個工廠??偨Y:工廠可以生產所有產品
工廠模式:一個產品一個工廠,十個產品十個工廠??偨Y:工廠只能生產一個產品
抽象工廠模式:N個產品M個工廠。總結:工廠可以靈活的生產商品。
還是按剛才的例子,我現在要賣蘋果,蘋果汁,梨子,梨子汁。
簡單工廠模式就是1個工廠賣四個產品。
工廠模式就是創建四個工廠賣四個產品。
抽象工廠模式就不一樣:我可以創建兩個工廠。一個專門賣蘋果類的,一個專門賣梨子類的,除了這樣的分類,還可以進行其他的分類,十分的靈活!
?定義:定義了一個接口用于創建相關或有依賴關系的對象族,而無需明確指定具體類。
舉例:(我們依然舉水果工廠的例子)
#include<iostream> using namespace std; class Produce_fruits;//聲明水果產品類 class Produce_fruits_juice;//聲明水果汁產品類 class Factory//工廠類 { public:Factory() {}~Factory() {}virtual Produce_fruits* create_produce(string name) = 0;//工廠生產產品,這里的純虛函數是為了讓子工廠生產產品//返回的是一個產品類指針,這就代表了一個產品//這里的name參數是為了返回想要的產品qwqvirtual Produce_fruits_juice* create_produce_juice(string name) = 0;//工廠生產產品,這里的純虛函數是為了讓子工廠生產產品//返回的是一個產品類指針,這就代表了一個產品//這里的name參數是為了返回想要的產品qwq }; class Produce_fruits { public:Produce_fruits() {}~Produce_fruits() {}virtual void show_myname() = 0;//這里定義的純虛函數是為了讓派生類去實現這個函數,有純虛函數的類是抽象類 }; class Produce_fruits_juice { public:Produce_fruits_juice() {}~Produce_fruits_juice() {}virtual void show_myname() = 0;//這里定義的純虛函數是為了讓派生類去實現這個函數,有純虛函數的類是抽象類 }; //現在我要開始創建具體的產品了 class Apple :public Produce_fruits//這是一個具體的蘋果類 { private:string name; public:Apple(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數 {cout << "我的名稱是:" << name << "(水果)" << endl;} }; class Pear :public Produce_fruits//這是一個具體的梨類 { private:string name; public:Pear(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數{cout << "我的名稱是:" << name << "(水果)" << endl;} }; class Produce_apple_juice :public Produce_fruits_juice//這是一個具體的蘋果類 { private:string name; public:Produce_apple_juice(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數 {cout << "我的名稱是:" << name << "(果汁)" << endl;} }; class Produce_pear_juice :public Produce_fruits_juice//這是一個具體的梨類 { private:string name; public:Produce_pear_juice(string new_name = ""){this->name = new_name;}virtual void show_myname()//重寫父類函數{cout << "我的名稱是:" << name << "(果汁)" << endl;} }; //下面開始創建具體的工廠類 class Factory_apple :public Factory//這是個蘋果工廠類 { public:Factory_apple() {}~Factory_apple() {}virtual Produce_fruits* create_produce(string name){Produce_fruits* my_produce = new Apple(name);//創建name的蘋果產品 return my_produce;}virtual Produce_fruits_juice* create_produce_juice(string name){Produce_fruits_juice* my_produce = new Produce_apple_juice(name);//創建name的蘋果汁產品 return my_produce;} }; class Factory_pear :public Factory//這是個梨工廠類 { public:Factory_pear() {}~Factory_pear() {}virtual Produce_fruits* create_produce(string name){Produce_fruits* my_produce = new Pear(name);//創建name的梨子產品 return my_produce;}virtual Produce_fruits_juice* create_produce_juice(string name){Produce_fruits_juice* my_produce = new Produce_pear_juice(name);//創建name的梨子汁產品 return my_produce;} }; //初期的搭建工作已經完成,總結一下,我們搭建了兩個抽象類:工廠類,水果產品類,果汁產品類;//產品派生類:蘋果類,梨類,蘋果汁類,梨汁類,//工廠派生類:蘋果工廠類,梨子工廠類。//現在我們要用這些東西了 int main() {Factory* my_factory_apple = new Factory_apple();//創建一個抽象工廠對象"升級"為蘋果工廠//這里的"升級"是我的理解 ,事實上是類型轉換Factory* my_factory_pear = new Factory_pear();//創建一個抽象工廠對象"升級"為梨子工廠//這里的"升級"是我的理解 ,事實上是類型轉換 Produce_fruits* my_produce_apple = my_factory_apple->create_produce("紅富士");//創建抽象產品對象,"升級"為蘋果工廠加工出來的紅富士 Produce_fruits* my_produce_pear = my_factory_pear->create_produce("鴨梨");//創建抽象產品對象,"升級"為梨子工廠加工出來的鴨梨Produce_fruits_juice* my_produce_apple_juice = my_factory_apple->create_produce_juice("紅蘋果汁");//創建抽象產品對象,"升級"為蘋果工廠加工出來的紅蘋果汁Produce_fruits_juice* my_produce_pear_juice = my_factory_pear->create_produce_juice("冰糖雪梨果汁");//創建抽象產品對象,"升級"為梨子工廠加工出來的冰糖雪梨果汁 my_produce_apple->show_myname();//產品顯示自己的名稱 my_produce_pear->show_myname();//產品顯示自己的名稱my_produce_apple_juice->show_myname();//產品顯示自己的名稱my_produce_pear_juice->show_myname();//產品顯示自己的名稱//下面是銷毀內存 delete my_factory_apple;my_factory_apple = nullptr;delete my_factory_pear;my_factory_pear = nullptr;delete my_produce_apple;my_produce_apple = nullptr;delete my_produce_pear;my_produce_pear = nullptr;delete my_produce_apple_juice;my_produce_apple_juice = nullptr;delete my_produce_pear_juice;my_produce_pear_juice = nullptr;return 0; }?
3、總結工廠模式適用的場合及使用的選擇
大量的產品需要創建,并且這些產品具有共同的接口 。
簡單工廠 : 用來生產同一等級結構中的任意產品。(不支持拓展增加產品)
工廠方法 :用來生產同一等級結構中的固定產品。(支持拓展增加產品) ??
抽象工廠 :用來生產不同產品族的全部產品。(支持拓展增加產品;支持增加產品族) ?
簡單工廠的適用場合:只有倫敦工廠(只有這一個等級),并且這個工廠只生產三種類型的pizza:chesse,pepper,greak(固定產品)。
工廠方法的適用場合:現在不光有倫敦工廠,還增設了紐約工廠(仍然是同一等級結構,但是支持了產品的拓展),這兩個工廠依然只生產三種類型的pizza:chesse,pepper,greak(固定產品)。
抽象工廠的適用場合:不光增設了紐約工廠(仍然是同一等級結構,但是支持了產品的拓展),這兩個工廠還增加了一種新的類型的pizza:chinese pizza(增加產品族)。
所以說抽象工廠就像工廠,而工廠方法則像是工廠的一種產品生產線。因此,我們可以用抽象工廠模式創建工廠,而用工廠方法模式創建生產線。比如,我們可以使用抽象工廠模式創建倫敦工廠和紐約工廠,使用工廠方法實現cheese pizza和greak pizza的生產。類圖如下: ? ??
總結一下三種模式:
簡單工廠模式就是建立一個實例化對象的類,在該類中對多個對象實例化。工廠方法模式是定義了一個創建對象的抽象方法,由子類決定要實例化的類。這樣做的好處是再有新的類型的對象需要實例化只要增加子類即可。抽象工廠模式定義了一個接口用于創建對象族,而無需明確指定具體類。抽象工廠也是把對象的實例化交給了子類,即支持拓展。同時提供給客戶端接口,避免了用戶直接操作子類工廠。
##### 特點: 簡單工廠模式:一個工廠N個產品 工廠模式:N個工廠N個產品 抽象工廠模式:N個工廠M個產品 ##### 缺點(相對): 簡單工廠模式:違背了開放封閉原則(改動源碼),產品多了會比較雜 工廠模式:產品多了會很雜,代碼量稍大,產品多了會比較雜 抽象工廠模式:違背了開放封閉原則(改動源碼),代碼量大,產品多了會比較非常雜 ##### 優點(相對): 簡單工廠模式:代碼量小,方便添加新的產品 工廠模式:不違背了開放封閉原則(不改動源碼),方便添加新的產品 抽象工廠模式:模式靈活,調用方便總結
- 上一篇: 两个cgi的莫名其妙的core dump
- 下一篇: 网络层:控制平面总结