設(shè)計模式簡介:
設(shè)計模式描述了對象如何進(jìn)行通信才能不牽涉相互的數(shù)據(jù)模型和方法另绩。
保持這種獨(dú)立性一直是一個好的面向?qū)ο蟪绦蛟O(shè)計的目標(biāo)。
Gang of Four的“Design Patterns: Elements of Resualbel Software”書將設(shè)計模式
歸納為三大類型,共23種些侍。
創(chuàng)建型模式 : 通常和對象的創(chuàng)建有關(guān)涝焙,涉及到對象實(shí)例化的方式垫言。(共5種模式)
行為型模式: 通常和對象間通信有關(guān)码耐。(共11種模式)
結(jié)構(gòu)型模式: 描述的是如何組合類和對象以獲得更大的結(jié)構(gòu)巍举。(共7種模式)
類模式描述的是如何使用繼承提供更有用的程序接口。
而對象模式描述的是如何通過使用對象組合或?qū)ο蟀谄渌麑ο罄铮? 將對象組合成更大的一個結(jié)構(gòu)蛋逾。
單例模式的適用范圍:
1集晚、單例模式可以保證:在一個應(yīng)用程序中,一個類有且只有一個實(shí)例区匣,
并提供一個訪問它的全局訪問點(diǎn)偷拔。
2、在程序設(shè)計過程中亏钩,有很多情況需要確保一個類只有一個實(shí)例条摸。
例如:
windows系統(tǒng)中只能有一個窗口管理器
某個程序中只能有一個日志輸出系統(tǒng)
一個GUI類庫中,有且只有一個ImageManager
還有其他無數(shù)種情況
教科書中的標(biāo)準(zhǔn)實(shí)現(xiàn):
教科書實(shí)現(xiàn).png
教課書中的標(biāo)準(zhǔn)實(shí)現(xiàn)的優(yōu)缺點(diǎn):
1铸屉、優(yōu)點(diǎn):該實(shí)現(xiàn)是一個"懶漢"單例模式,意味著只有在第一次調(diào)用GetInstance()切端,靜 態(tài)方法的時候才進(jìn)行內(nèi)存分配彻坛。如果整個程序不調(diào)用該靜態(tài)方法,則不會分配內(nèi)存踏枣。相對應(yīng)的是"餓漢"單例模式昌屉。
2、缺點(diǎn): 1) "懶漢"模式雖然有優(yōu)點(diǎn)茵瀑,但是每次調(diào)用GetInstance()靜態(tài)方法時间驮,
必須判斷NULL == m_instance,使程序相對開銷增大马昨。
2) 由于使用指針動態(tài)內(nèi)存分配竞帽,我們必須在程序結(jié)束時,
手動的調(diào)用ReleaseInstance()靜態(tài)方法鸿捧,進(jìn)行內(nèi)存的釋放屹篓。
3) 教科書標(biāo)準(zhǔn)實(shí)現(xiàn)最大的缺點(diǎn)是線程不安全。
根據(jù)該模式的定義匙奴,整個應(yīng)用程序中堆巧,不管是單線程,還是多線程,
都只能有且只有該類的一個實(shí)例谍肤。而在多線程中會導(dǎo)致多個實(shí)例的產(chǎn)生啦租,
從而導(dǎo)致運(yùn)行代碼不正確以及內(nèi)存的泄露。
教課書中的標(biāo)準(zhǔn)實(shí)現(xiàn)的線程不安全性演示:
線程不安全性演示代碼.png
VS2008線程不安全行演示效果.png
VS2015線程不安全演示效果.png
1荒揣、我們創(chuàng)建3個輔助線程篷角,外加main主線程,一共有4個線程乳附。
2内地、我們在每個輔助線程里面調(diào)用GetInstance()靜態(tài)方法,由于每個線程
回調(diào)函數(shù)速度非掣吵快阱缓,導(dǎo)致每個線程在判斷NULL==m_instance時,
都返回true,從而導(dǎo)致每個線程回調(diào)函數(shù)都會創(chuàng)建一個CSingleton1對
象并返回指向該對象的指針举农。
3荆针、我們根本沒辦法進(jìn)行CSingleton1的內(nèi)存釋放,因為在多線程中颁糟,
我們根本不知道是創(chuàng)建了1個航背、2個或3個CSingleton1的實(shí)例
Meyers Singleton Pattern實(shí)現(xiàn):
Meyers Singleton.png
Meyers Singleton Pattern的優(yōu)缺點(diǎn) :
1、優(yōu)點(diǎn):
1) 該實(shí)現(xiàn)是一個"懶漢"單例模式棱貌,意味著只有在第一次調(diào)用GetInstance()時才會
實(shí)例化玖媚。
2) 不需要每次調(diào)用GetInstance()靜態(tài)方法時,必須判斷NULL==m_instance,效
率相對高一些婚脱。
3) 使用對象而不是指針分配內(nèi)存今魔,因此自動回調(diào)用析構(gòu)函數(shù),不會導(dǎo)致內(nèi)存泄露障贸。
4) 在多線程下的確能夠保證有且只有一個實(shí)例產(chǎn)生错森。
2、缺點(diǎn):
在某些編譯器中篮洁,在多線程情況下涩维,并不是真正意義上的線程安全的實(shí)現(xiàn)
Meyers Singleton Pattern缺點(diǎn)演示:
我們修改一下前面線程函數(shù)
Instance2測試.png
VS2008Meyers單例線程不安全性演示.png
Meyers Singleton Pattern線程不安全性的原因:
這是因為C++中構(gòu)造函數(shù)并不是線程安全的。
C++中的構(gòu)造函數(shù)簡單來說分兩步:
第一步:內(nèi)存分配
第二步:初始化成員變量
由于多線程的關(guān)系袁波,可能當(dāng)我們在分配內(nèi)存好了以后瓦阐,還沒來得急初始化成員變量,就
進(jìn)行線程切換锋叨,另外一個線程拿到所有權(quán)后垄分,由于內(nèi)存已經(jīng)分配了,但是變量初始化還
沒進(jìn)行娃磺,因此打印成員變量的相關(guān)值會發(fā)生不一致現(xiàn)象薄湿。
結(jié)論:Meyers方式雖然能確保在多線程中產(chǎn)生唯一的實(shí)例,但是不能確保成員變量的值是否正確.
Next:
下一篇我們來實(shí)現(xiàn)一個線程安全,無內(nèi)存泄漏豺瘤,基于“懶漢”行為的單例模式吆倦。