單例模式--含義是某一個類,在一個程序中只有唯一的一個物件
###單例模式
單例模式是一種常見的設計模式
表示的含義是某一個類,在一個程序中只有唯一的一個物件,並且在語法角度上進行制約
- 一個類只能例項化出一個物件
- 必須由自己進行建立
- 它必須向整個系統提供訪問介面
(方案一)餓漢模式
物件定義後資料立即載入到記憶體,以空間換時間的做法
class Singleton_1 { public: static Singleton_1 *GetInstance()//靜態的成員函式,為外部提供介面 { return _inst; } protected: Singleton_1() {}; private: Singleton_1(const Singleton_1 & ) = delete; Singleton_1 operator = (const Singleton_1 &) = delete; static Singleton_1 *_inst;//靜態資料員。在該類範圍中只能定義一個 }; //需要先對靜態成員進行初始化 Singleton_1 *Singleton_1:: _inst = new Singleton_1(); //得到唯一的物件 Singleton_1 * inst_ptr = Singleton_1::GetInstance();
舉例驗證
#include <stdio.h> #include <iostream> using namespace std; template <class T> //類模板 class Singleton_1 { public: static T *GetInstance()//靜態的成員函式,用於訪問 T 資料 { return _inst; } private: Singleton_1(const T & ) = delete; Singleton_1 & operator = (const T &) = delete; static T* _inst;//靜態資料員。在該類範圍中只能定義一個 protected: Singleton_1() {}; //建構函式設為保護的是為了繼承下去 //這裡採用靜態成員意為 定義多個Signleton物件只能定義出一個T物件 }; //需要先對靜態成員進行初始化 template<class T> T *Singleton_1<T>:: _inst = new T(); //規定 T 類物件只能通過 Signleton物件定義出來 //獲得唯一的物件 int main() { int * ret_ptr_1 = Singleton_1<int>::GetInstance(); int * ret_ptr_2 = Singleton_1<int>::GetInstance(); *ret_ptr_2 = 9; *ret_ptr_1 = 8; printf("ret_1 :%d\n",*ret_ptr_1); printf("ret_2 :%d\n",*ret_ptr_2); printf("ret_ptr_1 :%p\n",ret_ptr_1); printf("ret_ptr_2 :%p\n",ret_ptr_2); return 0; }
結果顯示:
ret_1 :8
ret_2 :8
ret_ptr_1 :0x12c7c20
ret_ptr_2 :0x12c7c20
餓漢模式是一種執行緒安全的模式
(方案二)懶漢模式
物件定義出來 先不著急載入到記憶體,等到第一次使用的時候,再將資料載入到記憶體,以時間換空間的做法,其實也是一種延時載入
class Singleton_2
{
public:
static Singleton_2 *GetInstance()
{
if(_inst == NULL)
{//定義的時候先沒有開闢空間,只有在用的時候進行呼叫
//多次呼叫的時候,若不為空可以直接返回
_inst = new Singleton_2();
}
return _inst;
};
protected:
Singleton_2(){};
private:
static Singleton_2 * _inst;
Singleton_2(const Singleton_2 &) = delete; //防止拷貝
Singleton_2 operator = (const Singleton_2 &) = delete; //防止賦值
};
//靜態成員需要先進行初始化為NULL
Singleton_2 * Singleton_2::_inst = NULL;
Singleton_2 * inst_ptr= Singleton_2::GetInstance();
##注意
- 這種懶漢單例模式並不是一個執行緒安全模式,因為在判斷_inst是否為空和開闢空間並不是原子操作
- 若是兩個執行緒都執行到判斷這一步,就會建立兩個物件,就會出現邏輯錯誤
- 所以要在判斷和建立物件時加上互斥鎖
- 有為了效率問題,我們只需要在_inst為空的時候再進行加鎖
- 又為了防止編譯器過度優化,我們確保每次判斷的時候值都是從記憶體中讀取的,我們需要對私有成員加上 volatile關鍵字
(方案三)執行緒安全的懶漢模式
//執行緒安全的機制的懶漢模式
class Singleton_3
{
public:
static pthread_mutex_t lock;
volatile static Singleton_3 * GetInstance()
{
if(_inst == NULL)
{
//每次先判斷為空,即還有沒開闢空間的時候,在實施執行緒安全的措施
//否則的話,每一次呼叫函式的的時候都判斷就太浪費資源了
pthread_mutex_lock(&lock);
if(_inst == NULL)
{
_inst = new Singleton_3();
}
pthread_mutex_unlock(&lock);
}
return _inst;
}
protected:
//在建構函式種對互斥鎖進行初始化
Singleton_3()
{
pthread_mutex_init(&lock,NULL);
};
private:
volatile static Singleton_3 * _inst;
//防止編譯器進行優化
Singleton_3(const Singleton_3 &) = delete;
Singleton_3 * operator =(const Singleton_3 &) = delete;
};
//對靜態成員的初始化
pthread_mutex_t Singleton_3:: lock ;
volatile Singleton_3 * Singleton_3:: _inst = NULL;
int main()
{
volatile Singleton_3 * ret_ptr_1 = Singleton_3 ::GetInstance();
volatile Singleton_3 * ret_ptr_2 = Singleton_3 ::GetInstance();
volatile Singleton_3 * ret_ptr_3 = Singleton_3 ::GetInstance();
printf("ret_ptr_1 :%p\n",ret_ptr_1);
printf("ret_ptr_2 :%p\n",ret_ptr_2);
printf("ret_ptr_3 :%p\n",ret_ptr_3);
return 0;
}
結果:
ret_ptr_1 :0xbadc20
ret_ptr_2 :0xbadc20
ret_ptr_3 :0xbadc20
相關推薦
單例模式寫MySQL model類,簡單的增、刪、改、查
單例模式的用途,可用於資料庫操作 <?php Class Db { static private $whe;//條件 static private $tab;//表名 static private $lim;//分段變數 static private $ord
單例模式--含義是某一個類,在一個程序中只有唯一的一個物件
###單例模式 單例模式是一種常見的設計模式 表示的含義是某一個類,在一個程序中只有唯一的一個物件,並且在語法角度上進行制約 ###為什麼要有單例模式 在系統中,有些類必須保證只能創造出一個物件 我們windows系統中,只能開啟一個資源管理器,因為若是可以開
三種單例模式與Object祖先類
三種單例模式 object 單例有三種模式,懶漢式,餓漢式,和優化後的懶漢式 餓漢式單例模式: 餓漢式就像饑餓的人一樣先把事情都提前準備好,因為它是先在靜態屬性裏先提前構建好對象,然後再用靜態方法將對象返回出去,所以會提前占用資源,但是速度比較快。例如:懶漢式單例模式: 懶漢式就像懶人一樣要等到事
C++單例模式的模板基類
單例模式是很常用的設計模式,如果希望系統中某個類的物件只能有一個或者有一個就夠了,那麼便可以採用單例模式來解決。 下面用C++實現一個單例模板類,那麼其他的類只需繼承它,便可以成為單例類。 本例中使用了 CMutex類,是考慮多執行緒的情況,這個類的定義請參見筆者的另一篇部落格《C++簡
使用單例模式封裝網路工具類(okH)
我是用的是介面傳值,所以第一步是介面的建立 public interface NetWorkModelInterface { //失敗 void failure(Exception e); //成功 void success(String result)
單例模式之內部靜態類
利用內部靜態類實現單例模式public class Singleton { private Singleton(){ } public static Singleton getInstance() { return Nested.instance; }
java中實現單例模式的幾種方式,簡單易懂
一、餓漢式單例類 public class Singleton { private Singleton(){ } private static Singleton instance = new Singleton();
java設計模式(一)建立型模式之 單例模式(餓漢式,懶漢式,執行緒安全,雙重檢查)
1.介紹 單例模式是一種常用的軟體設計模式,其定義是單例物件的類只能允許一個例項存在。 2.實現思路與步驟 1).將該類的構造方法定義為私有方法,這樣其他處的程式碼就無法通過呼叫該類的構造方法來例項化該類的物件,只有通過該類提供的靜態
JAVA單例模式的各種寫法分析,最優為列舉
作用 單例模式(Singleton):保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點 適用場景 應用中某個例項物件需要頻繁的被訪問。 應用中每次啟動只會存在一個例項。如資料庫系統。 使用方式 懶漢式 public class Singleton { /* 持有私有靜
Java單例模式(餓漢式,懶漢式),我更願稱作(傳統銷售式,飢餓營銷式)
單例模式是一個很經典的設計模式,在java中無處不在。比如spring中的bean注入,工具類的編寫等。但是在剛接觸單例模式時候,我總對這個飽漢式和餓漢式的稱呼理解不好。下面來講一講我自己的理解。1)餓漢模式(傳統銷售式) class A{ private A(){} privat
單例模式的設計與實現,及效能測試
單例模式在實際應用中使用非常廣泛,比如日誌寫入,單例模式可以避免錯誤,資料庫連線可以避免鎖死,用例執行可以避免重複呼叫。 先是列舉實現法: public enum Singleton01 { INSTANCE; public void operator() { S
單例模式(泛型類)
在專案開發過程中,經常會涉及到多個採用單例模式的類,對每個類都要進行單例的處理,甚是不爽。 下面使用泛型類解決了這個問題,只要簡單繼承就可以了,程式碼如下: namespace LogHelper { using System; /// <sum
單例模式封裝的logging類庫的實現(Python)
import logging import sys def __singletion(cls): """ 單例模式的裝飾器函式 :param cls: 實體類 :return: 返回實體類物件 """ instances =
【設計模式】單例模式之執行緒類
好記性,不如爛筆頭。對於單例模式的理解和應用還是需要多多實踐,這次有感而發,寫份基於執行緒執行的單例模式。 單例模式該怎樣去實現:建構函式宣告為private或protect防止被外部函式例項化,內部
載入一個類時,其內部類是否同時被載入?靜態內部類單例模式
載入一個類時,其內部類是否同時被載入?下面我們做一個實驗來看一下。 Java程式碼 public class Outer { static { System.out.println("load outer class...");
載入一個類時,其內部類是否同時被載入?引申出單例模式的另一種實現方式...
載入一個類時,其內部類是否同時被載入?下面我們做一個實驗來看一下。public class Outer { static { System.out.println("load outer class..."); } //靜態內部類 sta
載入一個類時,其內部類是否同時被載入?引申出單例模式的另一種實現方式
載入一個類時,其內部類是否同時被載入?下面我們做一個實驗來看一下。 Java程式碼 1. public class Outer { 2. static { 3. System.out.println("load o
元類,__call__方法和單例模式
rom pan AR erro metaclass self acl clas HA 在python中一切皆對象的概念。 舉一個例子: class Chinese: country=“china” def __init__(self, name,age,s
python單例模式控制成只初始化一次,常規型的python單例模式在新式類和經典類中的區別。
spa alt let __main__ python2 urn 時間 div 分享 單例模式的寫法非常多,但常規型的單例模式就是這樣寫的,各種代碼可能略有差異,但核心就是要搞清楚類屬性 實例屬性,就很容易寫出來,原理完全一模一樣。 如下: 源碼: class
日期類時間類,日期時間類,單例模式,裝箱與拆箱,數字類隨機數,BigDecimal總結
方便 下標 時分秒 etime 相等 創建 rep style with 1.日期類,時間類,日期時間類 初步日期使用方法及格式轉換方法(舊方法): 格式://Mon Jul 30 11:26:05 CST 2018 年月日時分秒 CST代表北