標籤:
單例模式是最簡單的設計模式,就讓我像玩簡單的遊戲一樣寫下去吧。
v1: 簡單模式
和這個版本有過一面之緣,但不敢苟同。
class Singleton { private: Singleton() {} public: static Singleton * getIns() { static Singleton * ins = new Singleton(); return ins; }};
問題:何時析構不明確;最重要的是調用多次getIns函數會產生多個static Singleton指標,指向每次都調用都new出來的執行個體。
v2: 一般模式
典型寫法
class Singleton { private: Singleton() {} static Singleton * ins; public: static Singleton * getIns() { if(!ins) ins = new Singleton(); return ins; }};static Singleton * Singleton::ins = NULL;
問題:仍然未考慮析構問題;對象可能被複製出多個副本。
Java中由於允許在調用建構函式之前先初始設定變數,因此有這樣一種寫法:
public class Singleton { private Singleton() {} public static Singleton ins = new Singleton(); public static Singleton * getIns() { return ins; }};
簡潔明了,也是蠻OK啦,析構也省了,並且由於初始化這個語句是JVM做的,因此人工的同步也省了(不帶這麼欺負C++程式員的 = =)。
v2.1 一般模式2
v3: 加強模式
加入私人的複製建構函式以防出現單例對象的副本;加入一個內部靜態類,整個程式結束後,靜態類隨著其他靜態變數消亡,此時調用解構函式將ins析構。
class Singleton { private: Singleton() {} Singleton(const Singleton & s) {} Singleton & operator = (const Singleton & s) {} static Singleton * ins; public: static Singleton * getIns() { if(!ins) ins = new Singleton(); return ins; } class CGarbo // 內部類 { public: ~CGarbo() { if(Singleton::ins) delete Singleton::ins; } }; static CGarbo Garbo; }; static Singleton * Singleton::ins = NULL;
問題:不是安全執行緒的。
v4: hard模式
static Singleton * getIns() { pthread_mutex_init( &mutex_lock ); if(!ins) ins = new Singleton(); pthread_mutex_destory( &mutex_lock ); return ins; }
問題:不管ins是不是空,都要加鎖,代價高
v5: 再接再勵模式
當ins不為空白時,反正getIns函數不管讀寫,直接返回就好了,讀寫鎖盡可交給使用者。
static Singleton * getIns() { if(!ins) { pthread_mutex_init( &mutex_lock ); if(!ins) ins = new Singleton(); pthread_mutex_destory( &mutex_lock ); } return ins; }
自然,getIns加了鎖,析構的時候也同樣要加鎖。繼續學習,再接再勵!
【設計模式】C++單例模式的幾種寫法