1. 程式人生 > >設計模式之單例模式(C++程式碼實現)

設計模式之單例模式(C++程式碼實現)

1、單例模式:

單例模式:用來建立獨一無二的,只能夠有一個例項的物件。 單例模式的結構是設計模式中最簡單的,但是想要完全實現一個執行緒安全的單例模式還是有很多陷阱的。

2、應用場景:

共享資料或者共享訪問點;
建立一個物件需要消耗的資源過多,如訪問IO和資料庫等資源;
需要定義大量的靜態常量和靜態方法(工具類)

單例模式的應用場景:有一些物件其實只需要一個,比如:windows Task Manager (工作管理員)、windows 回收站、執行緒池、快取、對話方塊、處理偏好設定和登錄檔的物件、日誌物件、充當印表機、顯示卡等裝置的驅動程式物件。這些物件只能夠擁有一個例項,如果創建出了多個例項,就會導致一些程式的問題。程式的行為異常,資源使用的過量,或者導致不一致的結果。常用來管理共享的資源,比如資料庫的連線或者執行緒池。

3、優缺點:

優點:一個例項,減少記憶體開銷;減少系統開銷;避免對一個資源的多重佔用;設定全域性訪問點,優化和貢獻資源。

缺點:沒有藉口,擴充套件性差;不利於測試;與單一職責原則有衝突,單例模式把“要單例”和業務邏輯融合在一個類中。

4、實現

1、經典實現(執行緒不安全)

class Singleton 
{ 
  public: 
    static Singleton* getInstance(); 
  protected: 
    Singleton(){} 
  private: 
    static Singleton *p; 
}; 

Singleton* Singleton::p = NULL; 
Singleton* Singleton::getInstance() 
{ 
  if
(NULL == p) p = new Singleton(); return p; }
1、當兩個執行緒執行至if(instance==NULL)時,可能產生執行緒安全問題。

改進:在用到的時候在初始化,這樣程式效率比較高,但是有一個另外比較好的方法可以採用是提前初始化,將Instance設定為static之後直接初始化為Singleton物件,每次只需要執行返回操作即可。

class Singleton {
public:
    static Singleton* getInstance();

protected:

    Singleton();

private
: static Singleton *instance; }; //對單例直接進行初始化,而不再方法Instance中進行判斷。 Singleton* Singleton::instance = new Singleton; Singleton* Singleton::getInstance() {   return instance; } 這樣的話同樣會導致問題,就是如果單例本來資源比較多,但是不需要建立那麼早,就會消耗資源~ 2、另外一種提升因為同步導致的效能變差的方法稱為“雙重檢驗加鎖”。方法如下: class Singleton { public: static Singleton* getInstance(); protected: Singleton(); private: static Singleton* instance; } Singleton *Singleton::instance = NULL; Singleton* Singleton::getInstance() { //check 之前進行臨界區加鎖操作 //雙重檢驗加鎖 if(_instance == NULL ) { lock(); if( instance == NULL) { instance = new Singleton(); } Unlock(); } return _instance; } 思路是隻有在第一次建立的時候進行加鎖,當instance不為空的時候就不需要進行加鎖的操作,這樣就可以提升效能~

2、懶漢模式與餓漢模式

懶漢:故名思義,不到萬不得已就不會去例項化類,也就是說在第一次用到類例項的時候才會去例項化,所以上邊的經典方法被歸為懶漢實現;

餓漢:餓了肯定要飢不擇食。所以在單例類定義的時候就進行例項化。
特點與選擇

區別:由於要進行執行緒同步,所以在訪問量比較大,或者可能訪問的執行緒比較多時,採用餓漢實現,可以實現更好的效能。這是以空間換時間。在訪問量較小時,採用懶漢實現。這是以時間換空間。

1.加鎖實現執行緒安全的懶漢模式

class Singleton 
{ 
  public: 
    static pthread_mutex_t mutex; 
    static Singleton* getInstance(); 
  protected: 
    Singleton() 
    { 
      pthread_mutex_init(&mutex); 
    } 
  private: 
    static Singleton* p; 
}; 

pthread_mutex_t Singleton::mutex; 
Singleton* Singleton::p = NULL; 
Singleton* Singleton::getInstance() 
{ 
  if (NULL == p) 
  { 
    pthread_mutex_lock(&mutex); 
    if (NULL == p) 
      p = new Singleton(); 
    pthread_mutex_unlock(&mutex); 
  } 
  return p; 
}

2.內部靜態變數實現懶漢模式

class Singleton 
{ 
  public: 
  static pthread_mutex_t mutex; 
  static Singleton* getInstance(); 
  protected: 
    Singleton() 
    { 
      pthread_mutex_init(&mutex); 
    } 
}; 

pthread_mutex_t Singleton::mutex; 
Singleton* Singleton::getInstance() 
{ 
  pthread_mutex_lock(&mutex); 
  static singleton obj; 
  pthread_mutex_unlock(&mutex); 
  return &obj; 
}

餓漢模式

class Singleton 
{ 
  public: 
    static Singleton* getInstance(); 
  protected: 
    Singleton(){} 
  private: 
    static Singleton* p; 
}; 

Singleton* Singleton::p = new Singleton; 
Singleton* Singleton::getInstance() 
{ 
  return p; 
}