23种设计模式C++源码与UML实现--单例模式中的饿汉模式和懒汉模式
單例模式
單例模式是一種對(duì)象創(chuàng)建模式,使用單例模式,可以保證為一個(gè)類生成唯一的實(shí)例對(duì)象。也就是說(shuō)在這個(gè)程序空間該類只有一個(gè)實(shí)例對(duì)象。
GoF對(duì)單例的定義:保證一個(gè)類、只有一個(gè)實(shí)例存在,同時(shí)提供對(duì)該實(shí)例加以訪問(wèn)的全局訪問(wèn)方法。
單例模式UML圖
單例模式的目的就是保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。
使用單例模式的原因
在應(yīng)用系統(tǒng)開(kāi)發(fā)中,我們常常有以下需求:
- 多個(gè)線程公用一個(gè)socket資源,或者操作同一個(gè)對(duì)象
- 在整個(gè)程序空間需要使用全局變量,共享資源
- 大規(guī)模系統(tǒng)中,為了性能考慮,需要節(jié)省對(duì)象創(chuàng)建的時(shí)間等
實(shí)現(xiàn)步驟:
構(gòu)造函數(shù)私有化的作用:構(gòu)造函數(shù)私有化之后,則構(gòu)造該類的對(duì)象,必須在類內(nèi)部完成。
懶漢式單例模式
叫懶漢式的原因,是因?yàn)橹挥性儆玫臅r(shí)候才會(huì)創(chuàng)建類中的全局指針。
代碼實(shí)現(xiàn)如下:
#include <iostream>using namespace std;class Singleton { private:Singleton(){cout << "sluggard singleton construct start." << endl;}public:static Singleton *getInstance(void){if(NULL == m_psl) // 懶漢式,每次獲取實(shí)例都要判斷,在多線程中會(huì)存在問(wèn)題{m_psl = new Singleton;}return m_psl;}static void FreeInstance(){if(NULL != m_psl){delete m_psl;m_psl = NULL;}} private:static Singleton *m_psl; };// 靜態(tài)變量初始化的方法,要放到類的外面 Singleton *Singleton::m_psl = NULL;// 懶漢式,只有在使用的時(shí)候才會(huì)去創(chuàng)建 // 存在的問(wèn)題,多個(gè)線程同時(shí)首次調(diào)用時(shí),可能會(huì)出現(xiàn)創(chuàng)建多次的問(wèn)題(導(dǎo)致內(nèi)存泄漏)int main(int argc, char const *argv[]) {// 使用功能去全局獲取接口獲取資源Singleton *p1 = Singleton::getInstance(); Singleton *p2 = Singleton::getInstance();if(p1 == p2){cout << "p1 equal p2" << endl;}else{cout << "p1 not equal p2" << endl;}// 手動(dòng)釋放單例模式創(chuàng)建的唯一一個(gè)對(duì)象Singleton::FreeInstance();cout << "singleton." << endl;return 0; }編譯之后輸出結(jié)果:
sluggard singleton construct start. p1 equal p2 singleton.餓漢式
餓漢式,與懶漢式唯一的差別就是創(chuàng)建方式上,懶漢式是在首次調(diào)用的時(shí)候才創(chuàng)建,餓漢式是不管是否調(diào)用,在靜態(tài)指針初始化的時(shí)候就創(chuàng)建指針指向的對(duì)象。
#include <iostream>using namespace std;class Singleton { private:Singleton(){cout << "sluggard singleton construct start." << endl;}public:static Singleton *getInstance(void){return m_psl;}static void FreeInstance(){if(NULL != m_psl){delete m_psl;m_psl = NULL;}} private:static Singleton *m_psl; };// 靜態(tài)變量初始化的方法,要放到類的外面 // 餓漢式是在初始化指變量的時(shí)候就對(duì)其進(jìn)行創(chuàng)建,不管是否被調(diào)用 Singleton *Singleton::m_psl = new Singleton;int main(int argc, char const *argv[]) {// 使用功能去全局獲取接口獲取資源Singleton *p1 = Singleton::getInstance(); Singleton *p2 = Singleton::getInstance();if(p1 == p2){cout << "p1 equal p2" << endl;}else{cout << "p1 not equal p2" << endl;}// 手動(dòng)釋放單例模式創(chuàng)建的唯一一個(gè)對(duì)象Singleton::FreeInstance();cout << "singleton." << endl;return 0; }餓漢式執(zhí)行之后輸出結(jié)果:
sluggard singleton construct start. p1 equal p2 hungry singleton.兩者分析:
懶漢式因?yàn)槭褂玫臅r(shí)候才會(huì)創(chuàng)建內(nèi)存,所以當(dāng)多個(gè)線程同時(shí)使用的時(shí)候可能會(huì)出現(xiàn)多次創(chuàng)建的問(wèn)題,餓漢式不存在這個(gè)問(wèn)題。
懶漢式雖然有有點(diǎn),但是每次調(diào)用GetInstance()靜態(tài)方法都必須判斷靜態(tài)指針是否為NULL使程序相對(duì)開(kāi)銷增大,多喜愛(ài)能成中會(huì)導(dǎo)致多個(gè)實(shí)例產(chǎn)生,從而導(dǎo)致運(yùn)行代碼不正確以及內(nèi)存泄漏,也有可能是多次釋放資源。
這是因?yàn)镃++中構(gòu)造函數(shù)并不是線程安全的,C++中的構(gòu)造函數(shù)簡(jiǎn)單分為兩步
由于多線程的關(guān)系,可能內(nèi)存放分配好,還沒(méi)有給成員賦值,就發(fā)生了線程切換,導(dǎo)致下個(gè)線程中又申請(qǐng)了一遍內(nèi)存。
總結(jié)
以上是生活随笔為你收集整理的23种设计模式C++源码与UML实现--单例模式中的饿汉模式和懒汉模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: spring 多数据源 总结
- 下一篇: 【2015年第4期】大数据时代的数据挖掘