1.1 簡(jiǎn)單工廠模式
首先介紹簡(jiǎn)單工廠方法. 簡(jiǎn)單工廠可以向用戶隱蔽創(chuàng)造的實(shí)現(xiàn)細(xì)節(jié), 用戶只需要提供一些簡(jiǎn)單的好記的變量, 就能創(chuàng)建出一個(gè)完整的目標(biāo)對(duì)象.
所有的產(chǎn)品都繼承自抽象產(chǎn)品.
用戶持有一個(gè)工廠對(duì)象, 和一個(gè)抽象產(chǎn)品類的指針, 用這個(gè)指針去承接工廠產(chǎn)出的產(chǎn)品,
if(strName == "apple")
pRet = new apple();
else if (strName == "pear")
pRet = new pear();
else if.......
使用者只需要調(diào)用Factory->getObj("apple");就能得到一個(gè)想要的對(duì)象
但是同時(shí), 這個(gè)對(duì)象管理了太多的創(chuàng)建方法, 有點(diǎn)太龐大了, 并且創(chuàng)建新的工廠方法的時(shí)候, 修改了原有的邏輯, 不符合開閉原則.
工廠方法模式
這就衍生出了工廠方法模式.
四個(gè)角色:
- 抽象工廠類
- 實(shí)際工廠類
- 抽象產(chǎn)品類
- 實(shí)際產(chǎn)品類
抽象工廠是一個(gè)基類, 實(shí)際工廠都繼承自他.
根據(jù)需要, 寫出不同的實(shí)際工廠類, 這樣, 工廠的實(shí)例化被延遲到了子類中. 這樣, 無論我創(chuàng)建出多少新的工廠, 都不會(huì)去修改現(xiàn)有的工廠代碼.
用戶持有一個(gè)抽象工廠, 然后用抽象產(chǎn)品類去承接工廠產(chǎn)出的產(chǎn)品.
缺點(diǎn): 為了增加一個(gè)實(shí)際產(chǎn)品類, 要成對(duì)增加類的設(shè)計(jì). 同時(shí), 用戶還要同時(shí)持有兩個(gè)抽象類的指針(抽象工廠類和抽象產(chǎn)品類), 增加了用戶的復(fù)雜度.
1.2 抽象工廠模式
上一節(jié)講到了工廠方法模式, 而在抽象工廠模式中, 一個(gè)具體的工廠可以生產(chǎn)多種不同維度的產(chǎn)品.
比如basketball工廠可以生產(chǎn)basketball和basketball skirt;
football工廠可以生產(chǎn)football和football skirt.
我感覺, 就是多了一層維度.
優(yōu)點(diǎn): 用戶實(shí)例化一個(gè)具體的工廠之后, 相關(guān)的產(chǎn)品都可以從這一個(gè)工廠中得到, 隱藏細(xì)節(jié). 加入新產(chǎn)品無需修改原有系統(tǒng), 符合開閉原則.
缺點(diǎn)是, 如果在工廠已有的產(chǎn)品簇中, 增加一個(gè)新的產(chǎn)品, 就十分的困難, 要給所有已有的工廠(包括抽象工廠)都增加這個(gè)產(chǎn)品
1.3 建造者模式
所有角色:
- Product: 要制造的產(chǎn)品
- iWorker: 抽象建造者, 純虛函數(shù)描述了所有要實(shí)現(xiàn)的方法
- Worker1, Worker2: 繼承自iWorker, 實(shí)現(xiàn)了所有的虛函數(shù)
- Director: 指揮者, 選取特定的Worker. 傳入一個(gè)IWorker類型的指針來指定特定Worker.
和用戶屏蔽實(shí)現(xiàn)細(xì)節(jié), 用戶只是接觸了Director.
用戶持有一個(gè)IWorker的指針
IWorker指針可以指向任意一個(gè)new出來的Worker, 這個(gè)Worker傳入到Director中, 就可以得到一個(gè)特定的Product.
優(yōu)點(diǎn): 客戶端只需要指定特定的Worker并告訴Director就能得到結(jié)果, 其他的什么都不關(guān)心, 不同的Worker并無關(guān)聯(lián), 直接替換.
缺點(diǎn): 要求不同Worker生產(chǎn)的Product必須有很多共同點(diǎn), 因?yàn)橐肐Worker定義抽象的方法. 如果Product內(nèi)部變化復(fù)雜, 就會(huì)不得不定義很多的建造者(比如Product有10個(gè)維度都是正交變換的, 就會(huì)有n^10個(gè)Worker), 會(huì)導(dǎo)致系統(tǒng)變的很龐大.
1.4 原型模式
用戶持有一個(gè)原型, 那么就可以調(diào)用這個(gè)原型的clone方法來創(chuàng)建出新的對(duì)象.
每一個(gè)原型都繼承自抽象原型類. 抽象原型類唯一的作用就是聲明clone接口.
用戶再持有一個(gè)指針, 調(diào)用原型的clone方法, 就可以獲得一個(gè)新的原型. clone接口解決的就是深拷貝的問題(不然直接指針賦值就行了).
優(yōu)點(diǎn): 當(dāng)新對(duì)象創(chuàng)建復(fù)雜的時(shí)候, 使用原型直接就簡(jiǎn)化創(chuàng)建過程.
缺點(diǎn): 每一個(gè)類都要配備clone方法(也就是operator=方法), 位于類的內(nèi)部, 違背開閉原則.
1.5 單例模式
不做贅述, 單例模式想必大家已經(jīng)爛熟于心了.
這里提一下多線程如何保證的單例模式的線程安全.
Singleton* Singleton::getInstance()
{
if(m_singleton == NULL)
{
m_lock.Lock();
if(m_singleton ==NULL)
m_singleton = new Singleton();
m_lock.Unlock();
}
return m_singleton;
}
外部的if判斷不加鎖, 內(nèi)部又有一層if判斷, 這個(gè)判斷加鎖, 只要有了第一次的創(chuàng)建, 后續(xù)的創(chuàng)建都不需要走到內(nèi)部, 于是性能沒有降低很多.
C++11中還有std::once的方法, 保證創(chuàng)建只會(huì)被執(zhí)行一次, 也可以做到線程安全.