網(wǎng)站經(jīng)營(yíng)與建設(shè)優(yōu)化大師軟件下載
目錄
一、unique_lock
二、智能指針? (其實(shí)是一個(gè)類)
三、工廠模式
一、unique_lock
參考文章【1】,了解unique_lock與lock_guard的區(qū)別。
總結(jié):unique_lock使用起來(lái)要比lock_guard更靈活,但是效率會(huì)第一點(diǎn),內(nèi)存的占用也會(huì)大一點(diǎn)。
1.unique_lock的定義:
std::mutex mlock;
std::unique_lock<std::mutex> munique(mlock);
第二個(gè)參數(shù)可以是std::adopt_lock
std::unique_lock<std::mutex> munique(mlock,std::adopt_lock);
使用unique_lock和mutex來(lái)實(shí)現(xiàn)互斥鎖。unique_lock在構(gòu)造函數(shù)中獲取鎖,析構(gòu)函數(shù)中釋放鎖。adopt_lock參數(shù)告訴unique_lock構(gòu)造函數(shù),鎖已經(jīng)被其他線程獲取,unique_lock不需要再次獲取鎖,而是直接將鎖的所有權(quán)轉(zhuǎn)移給它自己。這樣做的好處是可以避免死鎖,因?yàn)閡niquelock的析構(gòu)函數(shù)會(huì)在任何情況下都釋放鎖,即使在發(fā)生異常的情況下也是如此。
也可以是:std::try_to_lock
std::unique_lock<std::mutex> munique(mlock, std::try_to_lock);
如果有一個(gè)線程被鎖住,而且執(zhí)行時(shí)間很長(zhǎng),那么另一個(gè)線程一般會(huì)被阻塞在那里,反而會(huì)造成時(shí)間的浪費(fèi)。那么使用了try_to_lock后,如果被鎖住了,它不會(huì)在那里阻塞等待,它可以先去執(zhí)行其他沒有被鎖的代碼。
也可以是std::defer_lock
std::unique_lock<std::mutex> munique(mlock, std::defer_lock);
表示暫時(shí)先不lock,之后手動(dòng)去lock。一般與unique_lock的成員函數(shù)搭配使用
2.unique_lock的成員函數(shù)
lock() 與 unlock()
當(dāng)使用了defer_lock參數(shù)時(shí),在創(chuàng)建了unique_lock的對(duì)象時(shí)就不會(huì)自動(dòng)加鎖,那么就需要借助lock這個(gè)成員函數(shù)來(lái)進(jìn)行手動(dòng)加鎖,當(dāng)然也有unlock來(lái)手動(dòng)解鎖。
try_lock():判斷是否能拿到鎖,如果拿不到鎖,返回false,如果拿到了鎖,返回true
release():解除unique_lock和mutex對(duì)象的聯(lián)系,并將原mutex對(duì)象的指針返回出來(lái)。如果之前的mutex已經(jīng)加鎖,需在后面自己手動(dòng)unlock解鎖
std::unique_lock<std::mutex> munique(mlock); // 這里是自動(dòng)lock
std::mutex *m = munique.release();
....
m->unlock();
std::thread t1(work1, std::ref(ans));
std::ref是C++標(biāo)準(zhǔn)庫(kù)中的一個(gè)函數(shù)模板,用于將一個(gè)對(duì)象包裝成一個(gè)引用。這個(gè)函數(shù)模板的作用是將一個(gè)對(duì)象的引用傳遞給一個(gè)函數(shù),而不是將對(duì)象本身傳遞給函數(shù)。這樣做的好處是可以避免對(duì)象的拷貝,提高程序的效率。
代碼塊中,std::ref被用于將ans對(duì)象包裝成一個(gè)引用,并將這個(gè)引用傳遞給work1函數(shù)的線程。這樣做的目的是讓work1函數(shù)在線程中對(duì)ans對(duì)象進(jìn)行操作,而不是對(duì)ans對(duì)象的拷貝進(jìn)行操作。
二、智能指針? (其實(shí)是一個(gè)類)
智能指針主要用于管理在堆上分配的內(nèi)存,它將普通的指針封裝為一個(gè)棧對(duì)象。當(dāng)棧對(duì)象的生存周期結(jié)束后,會(huì)在析構(gòu)函數(shù)中釋放掉申請(qǐng)的內(nèi)存,從而防止內(nèi)存泄漏。
C++ 11中最常用的智能指針類型為shared_ptr,它采用引用計(jì)數(shù)的方法,記錄當(dāng)前內(nèi)存資源被多少個(gè)智能指針引用。該引用計(jì)數(shù)的內(nèi)存在堆上分配。當(dāng)新增一個(gè)時(shí)引用計(jì)數(shù)加1,當(dāng)過期時(shí)引用計(jì)數(shù)減一。只有引用計(jì)數(shù)為0時(shí),智能指針才會(huì)自動(dòng)釋放引用的內(nèi)存資源。對(duì)shared_ptr進(jìn)行初始化時(shí)不能將一個(gè)普通指針直接賦值給智能指針,因?yàn)橐粋€(gè)是指針,一個(gè)是類。可以通過make_shared函數(shù)或者通過構(gòu)造函數(shù)傳入普通指針。并可以通過get函數(shù)獲得普通指針。
1.unique_ptr
unique_ptr保證同一時(shí)間內(nèi)只有一個(gè)智能指針可以指向該對(duì)象。它對(duì)于避免資源泄露,以new創(chuàng)建對(duì)象后因?yàn)榘l(fā)生異常而忘記調(diào)用delete特別有用。
兩個(gè)unique_ptr 不能指向一個(gè)對(duì)象,即 unique_ptr 不共享它所管理的對(duì)象。它無(wú)法復(fù)制到其他 unique_ptr,無(wú)法通過值傳遞到函數(shù)。
#include <iostream>
#include <string>
#include <memory>
int main() {std::unique_ptr<std::string> ps1, ps2;ps1 = std::make_unique<std::string>("hello");ps2 = std::move(ps1);ps1 = std::make_unique<std::string>("alexia");std::cout << *ps2 << *ps1 << std::endl;return 0;
}
2.shared_ptr
shared_ptr 允許多個(gè)指針指向同一個(gè)對(duì)象。利用引用計(jì)數(shù)的方式實(shí)現(xiàn)了對(duì)所管理的對(duì)象的所有權(quán)的分享,即允許多個(gè) shared_ptr 共同管理同一個(gè)對(duì)象,當(dāng)引用計(jì)數(shù)為 0 的時(shí)候,自動(dòng)釋放資源。
成員函數(shù):
use_count 返回引用計(jì)數(shù)的個(gè)數(shù)
unique 返回是否是獨(dú)占所有權(quán)
swap 交換兩個(gè) shared_ptr 對(duì)象(即交換所擁有的對(duì)象)
reset 放棄內(nèi)部對(duì)象的所有權(quán)或擁有對(duì)象的變更, 會(huì)引起原有對(duì)象的引用計(jì)數(shù)的減少
get 返回內(nèi)部對(duì)象(指針), 由于已經(jīng)重載了()方法, 因此和直接使用對(duì)象是一樣的.如
shared_ptr<int> sp(new int(1));
sp 與 sp.get()是等價(jià)的。
3.weak_ptr
share_ptr雖然已經(jīng)很好用了,但是有一點(diǎn)share_ptr智能指針還是有內(nèi)存泄露的情況,當(dāng)兩個(gè)對(duì)象相互使用一個(gè)shared_ptr成員變量指向?qū)Ψ?#xff0c;會(huì)造成循環(huán)引用,使引用計(jì)數(shù)失效,從而導(dǎo)致內(nèi)存泄漏。
weak_ptr 被設(shè)計(jì)為與 shared_ptr 共同工作,可以從一個(gè) shared_ptr 或者另一個(gè) weak_ptr 對(duì)象構(gòu)造而來(lái)。weak_ptr 是為了配合 shared_ptr 而引入的一種智能指針,它更像是 shared_ptr 的一個(gè)助手而不是智能指針,因?yàn)樗痪哂衅胀ㄖ羔樀男袨?#xff0c;沒有重載 operator* 和 operator-> ,因此取名為 weak,表明其是功能較弱的智能指針。它的最大作用在于協(xié)助 shared_ptr 工作,可獲得資源的觀測(cè)權(quán),像旁觀者那樣觀測(cè)資源的使用情況。觀察者意味著 weak_ptr 只對(duì) shared_ptr 進(jìn)行引用,而不改變其引用計(jì)數(shù),當(dāng)被觀察的 shared_ptr 失效后,相應(yīng)的 weak_ptr 也相應(yīng)失效。
使用方法:
使用 weak_ptr 的成員函數(shù) use_count() 可以觀測(cè)資源的引用計(jì)數(shù)。注意:weak_ptr不增加引用計(jì)數(shù)
另一個(gè)成員函數(shù) expired() 的功能等價(jià)于 use_count()==0,表示被觀測(cè)的資源(也就是 shared_ptr 管理的資源)已經(jīng)不復(fù)存在。
weak_ptr 可以使用一個(gè)非常重要的成員函數(shù)lock(),從被觀測(cè)的 shared_ptr 獲得一個(gè)可用的 shared_ptr 管理的對(duì)象, 從而操作資源。但當(dāng) expired()==true 的時(shí)候,lock() 函數(shù)將返回一個(gè)存儲(chǔ)空指針的 shared_ptr??偟膩?lái)說(shuō),weak_ptr 的基本用法總結(jié)如下:
shared_ptr<int> sp(new int(1));
weak_ptr<T> w; //創(chuàng)建空 weak_ptr,可以指向類型為 T 的對(duì)象
weak_ptr<T> w(sp); //與 shared_ptr 指向相同的對(duì)象,shared_ptr 引用計(jì)數(shù)不變。T必須能轉(zhuǎn)換為 sp 指向的類型
w=p; //p 可以是 shared_ptr 或 weak_ptr,賦值后 w 與 p 共享對(duì)象
w.reset(); //將 w 置空
w.use_count(); //返回與 w 共享對(duì)象的 shared_ptr 的數(shù)量
w.expired(); //若 w.use_count() 為 0,返回 true,否則返回 false
w.lock(); //如果 expired() 為 true,返回一個(gè)空 shared_ptr,否則返回非空 shared_ptr
#include <assert.h>#include <iostream>
#include <memory>
#include <string>using namespace std;int main() {shared_ptr<int> sp(new int(10));assert(sp.use_count() == 1);weak_ptr<int> wp(sp); // 從 shared_ptr 創(chuàng)建 weak_ptrassert(wp.use_count() == 1);if (!wp.expired()) { // 判斷 weak_ptr 觀察的對(duì)象是否失效shared_ptr<int> sp2 = wp.lock(); //使用 wp.lock() 創(chuàng)建一個(gè)新的 shared_ptr 時(shí),它又增加了一次引用計(jì)數(shù) *sp2 = 100;assert(wp.use_count() == 2);}assert(wp.use_count() == 1); //在 if 語(yǔ)句塊之外,wp.use_count() 的值仍然是1,因?yàn)?weak_ptr 并不會(huì)增加引用計(jì)數(shù)。cout << "int:" << *sp << endl;return 0;
}
這段代碼主要演示了如何使用?weak_ptr?來(lái)避免循環(huán)引用的問題。在這個(gè)例子中,我們創(chuàng)建了一個(gè)?shared_ptr?對(duì)象?sp,然后通過?weak_ptr?對(duì)象?wp?來(lái)觀察?sp。如果?sp?被銷毀了,那么?wp?也會(huì)自動(dòng)失效。在代碼中,我們通過?wp.expired()?來(lái)判斷?wp?是否失效,如果沒有失效,我們就可以通過?wp.lock()?來(lái)獲得一個(gè)?shared_ptr?對(duì)象?sp2,然后修改?sp2?所指向的值。最后,我們通過?use_count()?來(lái)檢查?sp?和?wp?的引用計(jì)數(shù)是否正確。
4.如何選擇智能指針:
(1)如果程序要使用多個(gè)指向同一個(gè)對(duì)象的指針,應(yīng)選擇 shared_ptr
- 將指針作為參數(shù)或者函數(shù)的返回值進(jìn)行傳遞的話,應(yīng)該使用 shared_ptr;
- 兩個(gè)對(duì)象都包含指向第三個(gè)對(duì)象的指針,此時(shí)應(yīng)該使用 shared_ptr 來(lái)管理第三個(gè)對(duì)象;
- STL 容器包含指針。很多 STL 算法都支持復(fù)制和賦值操作,這些操作可用于 shared_ptr,但不能用于 unique_ptr(編譯器發(fā)出 warning)和 auto_ptr(行為不確定)。如果你的編譯器沒有提供 shared_ptr,可使用 Boost 庫(kù)提供的 shared_ptr。
(2)如果程序不需要多個(gè)指向同一個(gè)對(duì)象的指針,則可使用 unique_ptr。如果函數(shù)使用 new 分配內(nèi)存,并返還指向該內(nèi)存的指針,將其返回類型聲明為 unique_ptr 是不錯(cuò)的選擇。
(3)為了解決 shared_ptr 的循環(huán)引用問題,使用?weak_ptr。
參考【2】【3】
三、工廠模式
工廠模式分為簡(jiǎn)單工廠模式、工廠方法模式和抽象工廠模式。
1.簡(jiǎn)單工廠模式
簡(jiǎn)單工廠模式又叫靜態(tài)方法模式(因?yàn)楣S類定義了一個(gè)靜態(tài)方法)。
將“類實(shí)例化的操作”與“使用對(duì)象的操作”分開,讓使用者不用知道具體參數(shù)就可以實(shí)例化出所需要的“產(chǎn)品”類,從而避免了在客戶端代碼中顯式指定,實(shí)現(xiàn)了解耦。也就是說(shuō),使用者可直接消費(fèi)產(chǎn)品而不需要知道其生產(chǎn)的細(xì)節(jié)。
模式組成:
組成 | 關(guān)系? | 作用 |
抽象產(chǎn)品(Product) | 具體產(chǎn)品的父類 | 描述產(chǎn)品的公共接口 |
具體產(chǎn)品(Concrete Product) | 抽象產(chǎn)品的子類;工廠類創(chuàng)建的目標(biāo)類 | 描述生產(chǎn)的具體產(chǎn)品 |
工廠(Factor) | 被外界調(diào)用 | 根據(jù)傳入不同參數(shù)從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例 |
使用步驟:
- 創(chuàng)建抽象產(chǎn)品類Product? ?:定義產(chǎn)品的公共接口
- 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類):定義生產(chǎn)的具體產(chǎn)品
- 創(chuàng)建工廠類:通過創(chuàng)建靜態(tài)方法傳入不同參數(shù),從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例
- 外界通過調(diào)用工廠類的靜態(tài)方法,傳入不同參數(shù)從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例
實(shí)列:某加工廠推出三個(gè)產(chǎn)品,使用簡(jiǎn)單工廠模式實(shí)現(xiàn)三種產(chǎn)品的生成
①創(chuàng)建抽象產(chǎn)品類Product:
class Product
{
public:virtual void Show() = 0;
};
②創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類):
class ProductA : public Product
{
public:void Show(){cout<<"I'm ProductA"<<endl;}
};class ProductB : public Product
{
public:void Show(){cout<<"I'm ProductB"<<endl;}
};class ProductC : public Product
{
public:void Show(){cout<<"I'm ProductC"<<endl;}
};
③創(chuàng)建工廠類:通過創(chuàng)建靜態(tài)方法傳入不同參數(shù),從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例。
typedef enum ProductTypeTag
{TypeA,TypeB,TypeC
}PRODUCTTYPE;class Factory
{
public:static Product* CreateProduct(PRODUCTTYPE type){switch (type){case TypeA:return new ProductA();case TypeB:return new ProductB();case TypeC:return new ProductC();default:return NULL;}}
};
④外界通過調(diào)用工廠類的靜態(tài)方法,傳入不同參數(shù)從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例
int main(int argc, char *argv[])
{//創(chuàng)造工廠對(duì)象Factory *ProductFactory = new Factory();//從工廠對(duì)象創(chuàng)造產(chǎn)品A對(duì)象Product *productObjA = ProductFactory->CreateProduct(TypeA);if (productObjA != NULL)productObjA->Show();Product *productObjB = ProductFactory->CreateProduct(TypeB);if (productObjB != NULL)productObjB->Show();Product *productObjC = ProductFactory->CreateProduct(TypeC);if (productObjC != NULL)productObjC->Show();delete ProductFactory;ProductFactory = NULL;delete productObjA;productObjA = NULL;delete productObjB;productObjB = NULL; delete productObjC;productObjC = NULL;return 0;
}
?優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
- 把初始化實(shí)例時(shí)的工作放到工廠里進(jìn)行,使代碼更容易維護(hù)。
- 將“類實(shí)例化的操作”與“使用對(duì)象的操作”分開,讓使用者不用知道具體參數(shù)就可以實(shí)例化出所需要的“產(chǎn)品”類,
缺點(diǎn):
- 工廠類集中了所有實(shí)例(產(chǎn)品)的創(chuàng)建邏輯,一旦這個(gè)工廠不能正常工作,整個(gè)系統(tǒng)都會(huì)受到影響;
- 違背“開放 - 關(guān)閉原則”,一旦添加新產(chǎn)品就不得不修改工廠類的邏輯,這樣就會(huì)造成工廠邏輯過于復(fù)雜。
- 簡(jiǎn)單工廠模式由于使用了靜態(tài)工廠方法,靜態(tài)方法不能被繼承和重寫,會(huì)造成工廠角色無(wú)法形成基于繼承的等級(jí)結(jié)構(gòu)。
2.工廠方法模式
針對(duì)簡(jiǎn)答工廠模式問題,設(shè)計(jì)了工廠方法模式。工廠父類負(fù)責(zé)定義創(chuàng)建對(duì)象的公共接口,而子類則負(fù)責(zé)生成具體的對(duì)象。
將類的實(shí)例化(具體產(chǎn)品的創(chuàng)建)延遲到工廠類的子類(具體工廠)中完成,即由子類來(lái)決定應(yīng)該實(shí)例化(創(chuàng)建)哪一個(gè)類。
之所以可以解決簡(jiǎn)單工廠的問題,是因?yàn)?span style="color:#fe2c24;">工廠方法模式把具體產(chǎn)品的創(chuàng)建推遲到工廠類的子類(具體工廠)中,此時(shí)工廠類不再負(fù)責(zé)所有產(chǎn)品的創(chuàng)建,而只是給出具體工廠必須實(shí)現(xiàn)的接口,這樣工廠方法模式在添加新產(chǎn)品的時(shí)候就不修改工廠類邏輯而是添加新的工廠子類,符合開放封閉原則。
模式組成:
組成 | 關(guān)系? | 作用 |
抽象產(chǎn)品(Product) | 具體產(chǎn)品的父類 | 描述具體產(chǎn)品的公共接口 |
具體產(chǎn)品(Concrete Product) | 抽象產(chǎn)品的子類;工廠類創(chuàng)建的目標(biāo)類 | 描述生產(chǎn)的具體產(chǎn)品 |
抽象工廠(Factor) | 具體工廠的父類 | 描述具體工廠的公共接口 |
具體工廠(Concrete Factor) | 抽象工廠的子類;被外界調(diào)用 | 描述具體工廠 |
使用步驟:
- 創(chuàng)建抽象產(chǎn)品類 ,定義具體產(chǎn)品的公共接口;
- 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類):定義生產(chǎn)的具體產(chǎn)品;
- 創(chuàng)建抽象工廠類,定義具體工廠的公共接口;
- 創(chuàng)建具體工廠類(繼承抽象工廠類),定義創(chuàng)建對(duì)應(yīng)具體產(chǎn)品實(shí)例的方法;
- 外界通過調(diào)用具體工廠類的方法,從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例
實(shí)例:某加工廠原來(lái)只生產(chǎn)A類產(chǎn)品,但新的訂單要求生產(chǎn)B類產(chǎn)品,由于改變?cè)瓉?lái)工廠的配置比較困難,因此開設(shè)工廠B生產(chǎn)B類產(chǎn)品。
#include <iostream>
using namespace std;//1.創(chuàng)建抽象產(chǎn)品類
class Product
{
public:virtual void Show() = 0;
};
//2.創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類)
class ProductA : public Product
{
public:void Show(){cout<< "I'm ProductA"<<endl;}
};class ProductB : public Product
{
public:void Show(){cout<< "I'm ProductB"<<endl;}
};//3.創(chuàng)建抽象工廠類
class Factory
{
public:virtual Product *CreateProduct() = 0;
};//4.創(chuàng)建具體工廠類(繼承抽象工廠類),定義創(chuàng)建對(duì)應(yīng)具體產(chǎn)品實(shí)例的方法;
class FactoryA : public Factory
{
public:Product *CreateProduct(){return new ProductA ();}
};class FactoryB : public Factory
{
public:Product *CreateProduct(){return new ProductB ();}
};//5.外界通過調(diào)用具體工廠類的方法,從而創(chuàng)建不同具體產(chǎn)品類的實(shí)例
int main(int argc , char *argv [])
{Factory *factoryA = new FactoryA ();Product *productA = factoryA->CreateProduct();productA->Show();Factory *factoryB = new FactoryB ();Product *productB = factoryB->CreateProduct();productB->Show();if (factoryA != NULL){delete factoryA;factoryA = NULL;}if (productA != NULL){delete productA;productA = NULL;}if (factoryB != NULL){delete factoryB;factoryB = NULL;}if (productB != NULL){delete productB;productB = NULL;}system("pause");return 0;
}
優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
- 符合開-閉原則。新增一種產(chǎn)品時(shí),只需要增加相應(yīng)的具體產(chǎn)品類和相應(yīng)的工廠子類即可。(簡(jiǎn)單工廠模式需要修改工廠類的判斷邏輯)
- 符合單一職責(zé)原則。每個(gè)具體工廠類只負(fù)責(zé)創(chuàng)建對(duì)應(yīng)的產(chǎn)品。(簡(jiǎn)單工廠中的工廠類存在復(fù)雜的switch邏輯判斷)
- 不使用靜態(tài)工廠方法,可以形成基于繼承的等級(jí)結(jié)構(gòu)。(簡(jiǎn)單工廠模式的工廠類使用靜態(tài)工廠方法)
缺點(diǎn):
- 添加新產(chǎn)品時(shí),除了增加新產(chǎn)品類外,還要提供與之對(duì)應(yīng)的具體工廠類,系統(tǒng)類的個(gè)數(shù)將成對(duì)增加,在一定程度上增加了系統(tǒng)的復(fù)雜度
- 由于考慮到系統(tǒng)的可擴(kuò)展性,需要引入抽象層,在客戶端代碼中均使用抽象層進(jìn)行定義,增加了系統(tǒng)的抽象性和理解難度
- 一個(gè)具體工廠只能創(chuàng)建一種具體產(chǎn)品
3.抽象工廠模式
工廠方法模式存在一個(gè)嚴(yán)重的問題:一個(gè)具體工廠只能創(chuàng)建一類產(chǎn)品;而在實(shí)際過程中,一個(gè)工廠往往需要生產(chǎn)多類產(chǎn)品。使用了一種新的設(shè)計(jì)模式:抽象工廠模式。
定義:創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無(wú)須指定它們具體的類;具體的工廠負(fù)責(zé)實(shí)現(xiàn)具體的產(chǎn)品實(shí)例。
允許使用抽象的接口來(lái)創(chuàng)建一組相關(guān)產(chǎn)品,而不需要知道或關(guān)心實(shí)際生產(chǎn)出的具體產(chǎn)品是什么,這樣就可以從具體產(chǎn)品中被解耦。
模式組成:
組成 | 關(guān)系? | 作用 |
抽象產(chǎn)品族(AbstractProduct | 抽象產(chǎn)品的父類 | 描述抽象產(chǎn)品的公共接口 |
抽象產(chǎn)品(Product) | 具體產(chǎn)品的父類 | 描述具體產(chǎn)品的公共接口 |
具體產(chǎn)品(Concrete Product) | 抽象產(chǎn)品的子類;工廠類創(chuàng)建的目標(biāo)類 | 描述生產(chǎn)的具體產(chǎn)品 |
抽象工廠(Factor) | 具體工廠的父類 | 描述具體工廠的公共接口 |
具體工廠(Concrete Factor) | 抽象工廠的子類;被外界調(diào)用 | 描述具體工廠 |
使用步驟:
- 創(chuàng)建抽象產(chǎn)品族類 ,定義抽象產(chǎn)品的公共接口;
- 創(chuàng)建抽象產(chǎn)品類 (繼承抽象產(chǎn)品族類),定義具體產(chǎn)品的公共接口;
- 創(chuàng)建具體產(chǎn)品類(繼承抽象產(chǎn)品類) & 定義生產(chǎn)的具體產(chǎn)品;
- 創(chuàng)建抽象工廠類,定義具體工廠的公共接口;
- 創(chuàng)建具體工廠類(繼承抽象工廠類),定義創(chuàng)建對(duì)應(yīng)具體產(chǎn)品實(shí)例的方法;
- 客戶端通過實(shí)例化具體的工廠類,并調(diào)用其創(chuàng)建不同目標(biāo)產(chǎn)品的方法 創(chuàng)建不同具體產(chǎn)品類的實(shí)例
實(shí)例:某廠有兩個(gè)加工廠A和B分別生產(chǎn)鞋和衣服,隨著訂單的增加,A廠所在地有了衣服的訂單,B廠所在地有了鞋子的訂單,再開新的工廠顯然是不現(xiàn)實(shí)的,因此在原來(lái)的工廠增加生產(chǎn)需求的功能,即A生產(chǎn)鞋+衣服,B生產(chǎn)衣服+鞋。
#include <iostream>
using namespace std;
//這個(gè)代碼沒有抽象產(chǎn)品族類// 抽象產(chǎn)品A
class ProductA
{
public:virtual void Show() = 0;
};//具體的產(chǎn)品
class ProductA1 : public ProductA
{
public:void Show(){cout<<"I'm ProductA1"<<endl;}
};class ProductA2 : public ProductA
{
public:void Show(){cout<<"I'm ProductA2"<<endl;}
};// 抽象產(chǎn)品B
class ProductB
{
public:virtual void Show() = 0;
};class ProductB1 : public ProductB
{
public:void Show(){cout<<"I'm ProductB1"<<endl;}
};class ProductB2 : public ProductB
{
public:void Show(){cout<<"I'm ProductB2"<<endl;}
};// Factory
class Factory
{
public:virtual ProductA *CreateProductA() = 0;virtual ProductB *CreateProductB() = 0;
};//具體工廠A生產(chǎn)A1和B1
class Factory1 : public Factory
{
public:ProductA *CreateProductA(){return new ProductA1();}ProductB *CreateProductB(){return new ProductB1();}
};class Factory2 : public Factory
{ProductA *CreateProductA(){return new ProductA2();}ProductB *CreateProductB(){return new ProductB2();}
};int main(int argc, char *argv[])
{Factory *factoryObj1 = new Factory1();ProductA *productObjA1 = factoryObj1->CreateProductA();ProductB *productObjB1 = factoryObj1->CreateProductB();productObjA1->Show();productObjB1->Show();Factory *factoryObj2 = new Factory2();ProductA *productObjA2 = factoryObj2->CreateProductA();ProductB *productObjB2 = factoryObj2->CreateProductB();productObjA2->Show();productObjB2->Show();if (factoryObj1 != NULL){delete factoryObj1;factoryObj1 = NULL;}if (productObjA1 != NULL){delete productObjA1;productObjA1= NULL;}if (productObjB1 != NULL){delete productObjB1;productObjB1 = NULL;}if (factoryObj2 != NULL){delete factoryObj2;factoryObj2 = NULL;}if (productObjA2 != NULL){delete productObjA2;productObjA2 = NULL;}if (productObjB2 != NULL){delete productObjB2;productObjB2 = NULL;}system("pause");return 0;
}
優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
- 抽象工廠模式將具體產(chǎn)品的創(chuàng)建延遲到具體工廠的子類中,這樣將對(duì)象的創(chuàng)建封裝起來(lái),可以減少客戶端與具體產(chǎn)品類之間的依賴,從而使系統(tǒng)耦合度低,這樣更有利于后期的維護(hù)和擴(kuò)展;
- 新增一種產(chǎn)品類時(shí),只需要增加相應(yīng)的具體產(chǎn)品類和相應(yīng)的工廠子類即可
缺點(diǎn):
- 抽象工廠模式很難支持新種類產(chǎn)品的變化。因?yàn)槌橄蠊S接口中已經(jīng)確定了可以被創(chuàng)建的產(chǎn)品集合,如果需要添加新產(chǎn)品,此時(shí)就必須去修改抽象工廠的接口,這樣就涉及到抽象工廠類的以及所有子類的改變
參考【4】 【5】?