C 單例模式

2021-09-19 09:22:17 字數 3621 閱讀 1449

單例模式也稱為單件模式、單子模式,是一種常用的軟體設計模式。在它的核心結構中只包含乙個被稱為單例的特殊類,即設計的乙個類成為單例。通過單例模式可以保證系統中乙個這個類只有乙個例項。即乙個類只有乙個物件例項。(設計模式(design pattern)是一套被反覆使用、多數人知曉的、經過分類的、**設計經驗的總結)。單例模式是設計模式中最簡單的形式之一。用一種只允許生成物件類的唯一例項的機制,「阻止」所有想要生成物件的訪問。使用工廠方法來限制例項化過程。這個方法應該是靜態方法(類方法),因為讓類的例項去生成另乙個唯一例項毫無意義。

目標功能:一是設計某個類且只能有乙個例項;二是這個類必須自行建立這個例項;三是類必須自行向整個系統提供這個例項。保證全域性只有乙個唯一例項物件;提供獲取這個唯一例項的介面。

具體實現要點:一是單例模式的類只提供私有的建構函式;二是類定義中含有乙個該類的靜態私有物件,三是該類提供了乙個靜態的公有的函式用於建立或獲取它本身的靜態私有物件(只能在類裡建立物件)。

單例模式通過類本身來管理其唯一例項,這種特性提供了解決問題的方法。唯一的例項是類的乙個普通物件,但設計這個類時,讓它只能建立乙個例項並提供對此例項的全域性訪問。唯一例項類singleton在靜態成員函式中隱藏建立例項的操作。習慣上把這個成員函式叫做getinstance(),它的返回值是唯一例項的指標。

優點:(1)例項控制:單例模式會阻止其他物件例項化其自己的單例物件的副本,從而確保所有物件都訪問唯一例項。

(2)靈活性:因為類控制了例項化過程,所以類可以靈活更改例項化過程。

缺點:(1)開銷:雖然數量很少,但如果每次物件請求引用時都要檢查是否存在類的例項,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。

(2)可能的開發混淆:使用單例物件(尤其在類庫中定義的物件)時,開發人員必須記住自己不能使用new關鍵字例項化物件。因為可能無法訪問庫源**,因此應用程式開發人員可能會意外發現自己無法直接例項化此類。

(3)物件生存期:不能解決刪除單個物件的問題。在提供記憶體管理的語言中(例如基於.net framework的語言),只有單例類能夠導致例項被取消分配,因為它包含對該例項的私有引用。在某些語言中(如 c++),其他類可以刪除物件例項,但這樣會導致單例類**現懸浮引用。。

(1)懶漢模式 ---lazy load + 相對而言 複雜--各種場景下都適用

//設計乙個類,成為單例

class lock  //自造輪子

~lock()

private:

lock(const lock&);

lock& operator=(const lock&);

mutex& _mx;

};//懶漢模式

class singleton

return _inst;

}static void delinstance()

}struct gc

};void print()

private:

//2.建構函式定義為私有

singleton()

:_a(0)

{}~singleton()

{}//防拷貝

singleton(const singleton&);

singleton& operator=(const singleton&);

int _a;

//3.靜態私有物件

static singleton* _inst;

static mutex _mtx;

};singleton* singleton::_inst = null;

mutex singleton::_mtx;

static singleton::gc gc;

void test()

使用者訪問唯一例項的方法只有getinstance()成員函式。如果不通過這個函式,任何建立例項的嘗試都將失敗,因為類的建構函式是私有的。getinstance()使用懶惰初始化,也就是說它的返回值是當這個函式首次被訪問時被建立的。這是一種防彈設計——所有getinstance()之後的呼叫都返回相同例項的指標:

singleton* p1 = singleton :: getinstance();

singleton* p2 = p1->getinstance();

singleton & ref = * singleton :: getinstance();

對getinstance稍加修改,這個設計模板便可以適用於可變多例項情況。

關於singleton(const singleton);和 singleton & operate = (const singleton&);函式,需要宣告成私有的,並且只宣告不實現。這樣,如果用上面的方式來使用單例時,不管是在友元類中還是其他的,編譯器都是報錯。考慮到執行緒安全、異常安全用了鎖。

注:上述實現的單例屬於 "懶漢模式"的單例。即:都採取的是用時間換空間的思想。

(2)餓漢模式  ----一開始(main) load  簡潔 適用性會受到限制 動態庫

//餓漢模式

class singleton2

void print()

private:

//2.建構函式定義為私有

singleton2()

:_a(0)

{}//防拷貝

singleton2(const singleton2&);

singleton2& operator=(const singleton2&);

int _a;

//3.靜態私有物件

static singleton2* _inst;

};  // 外部初始化(進入主函式之前)

const singleton* singleton::pinstance = new _inst;

void test()

這是一種較簡單的實現方式,但問題也較多,應用用不太廣泛。第一種方法可適用於各種複雜情況下。

注意:靜態例項初始化保證了執行緒安全。

reason:靜態例項初始化在程式開始時進入主函式之前就由主線程以單執行緒方式完成了初始化。可以不用考慮多執行緒的問題。因此這種模式在效能需求較高時,可避免頻繁的鎖競爭。

兩種模式的區別:餓漢式在類建立的同時就已經建立好乙個靜態的物件供系統使用,以後不在改變,執行緒安全。所以載入類時比較慢,但執行時獲取物件的速度比較快。懶漢模式在程式執行時建立例項物件,執行緒不安全,需要加鎖。但載入類時比較快,而在執行時獲取物件的速度比較慢,所以推薦使用餓漢模式。

通俗來講就是懶漢式是在你真正需要使用例項物件時才去建立這個單例物件;餓漢式不管你用不用都先給你建立這個單例物件。

對於系統中的某些類來說,只有乙個例項很重要,例如,乙個系統中可以存在多個列印任務,但是只能有乙個正在工作的任務;乙個系統只能有乙個視窗管理器或檔案系統;乙個系統只能有乙個計時工具或id(序號)生成器。如在windows中就只能開啟乙個任務管理器。如果不使用機制對視窗物件進行唯一化,將彈出多個視窗,如果這些視窗顯示的內容完全一致,則是重複物件,浪費記憶體資源;如果這些視窗顯示的內容不一致,則意味著在某一瞬間系統有多個狀態,與實際不符,也會給使用者帶來誤解,不知道哪乙個才是真實的狀態。因此有時確保系統中某個物件的唯一性即乙個類只能有乙個例項非常重要。

C 單例模式

include using namespace std 單例類的c 實現 class singleton 構造方法實現 singleton singleton void singleton setvar int var main int main int argc,char argv return ...

C 單例模式

實現方式一 include template typename t class singleton boost noncopyable static void init private static pthread once t ponce statict value template typena...

C 單例模式

效率有點低,但是還算安全的單例模式,靜態成員實現方式 class singleton public static singleton getinstance singleton singleton getinstance unlock return m instance 內部靜態例項的懶漢模式,c ...