c# 單例模式的實現(xiàn)
記一下學(xué)習(xí)單例模式的筆記:
單例就是要保證該類僅有一個實例。實現(xiàn)完全封閉的單例(外部不能new)其實就要兩點要求:
- 全局訪問:需要一個該類型的全局靜態(tài)變量,每次獲取實例時都要判斷它是否null,不存在new,存在通過一個方法直接返回該值獲取實例來保證對象唯一;
- 實例化控制:new實例不能外部new、造成實例不唯一,需要一個私有構(gòu)造器禁用共有構(gòu)造器。
根據(jù)new實例的時機,分為餓漢式和懶漢式:
一、 餓漢式單例:靜態(tài)變量初始化時new
特點:加載時new,一開始全局就存在該唯一實例,每次用到只要獲取就行,提前占用系統(tǒng)資源但不存在線程安全問題。代碼如下:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton GetInstance()
{
return instance;
}
}
二、 懶漢式單例:需要該實例的時候再new
特點:真正需要用到的時候才實例化,不提前占用資源但多個線程同時用到該實例時,會存在判斷靜態(tài)變量都為null都去new而產(chǎn)生多個實例的情況。有線程安全問題,但可以用雙重鎖定解決。
單線程懶漢單例代碼如下:
public class Singleton
{
private static Singleton instance = null;
private Singleton() { }
public static Singleton GetInstance()
{
if (instance == null)
instance = new Singleton();
return instance;
}
}
多線程懶漢單例代碼如下:
public class Singleton
{
private static Singleton instance = null;
private static readonly object obj = new object();
private Singleton() { }
public static Singleton GetInstance()
{
//雙重鎖定
if (instance == null)//只有為null需要實例化處理時才進行加鎖,提高性能避免不必要的等待
{
lock (obj)
{
if (instance == null)//避免其他線程等待鎖釋放期間有線程已經(jīng)實例化,從而造成多個實例
instance = new Singleton();
}
}
return instance;
}
}
三、 注冊式單例
介紹一個有意思的單例-泛型注冊式,是對單例的擴展,主要了解它的設(shè)計思想。
其實每個類單例模式實現(xiàn)代碼都是差不多的:
- 相同結(jié)構(gòu)和成員(字段、屬性、行為等):是否可以考慮進行抽象提取一個公共的調(diào)用接口?
- 成員類型或輸入輸出具體類型不是固定的:是否可以考慮設(shè)計一個適用于不同類型的通用處理方式而不都是Object?這個適用不同類型通用解決就要用到泛型。
實現(xiàn)代碼如下(例子使用餓漢式,當(dāng)然也可以用懶漢式):
public abstract class Singleton<T> where T:class,new()
{
private static readonly T instance = new T();
protected Singleton() { }
public static T GetSingleton()//獲取單例
{
return instance;
}
}
public class Person : Singleton<Person> { }
可以看到這種單例通過繼承的方式,既可以new實例也可以獲取單例實例。如果要實現(xiàn)上面的完全封閉(禁用外部new),也可以完全在Person類中寫個私有構(gòu)造器在Singleton<T>類中實例的獲取new T()改為反射調(diào)用私有構(gòu)造器的方式實現(xiàn),總感覺怪怪的。
下面是主程序調(diào)用該單例方法:
static void Main(string[] args)
{
Person p1 = Person.GetSingleton();
Person p2 = Singleton<Person>.GetSingleton();
if (object.ReferenceEquals(p1, p2))
{
Console.WriteLine("兩個對象是同一實例");
}
Console.ReadKey();
}
輸出結(jié)果:

以上就是c# 單例模式的實現(xiàn)方法的詳細內(nèi)容,更多關(guān)于c# 單例模式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#使用Enum.TryParse()實現(xiàn)枚舉安全轉(zhuǎn)換
這篇文章介紹了C#使用Enum.TryParse()實現(xiàn)枚舉安全轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08
c# richtextbox更新大量數(shù)據(jù)不卡死的實現(xiàn)方式
這篇文章主要介紹了c# richtextbox更新大量數(shù)據(jù)不卡死的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
Unity 使用TexturePacker打包圖集的操作方法
這篇文章主要介紹了Unity 使用TexturePacker打包圖集的操作方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08
implicit關(guān)鍵字做自定義類型隱式轉(zhuǎn)換的方法
implicit 關(guān)鍵字用于聲明隱式的用戶定義類型轉(zhuǎn)換運算符。如果轉(zhuǎn)換過程可以確保不會造成數(shù)據(jù)丟失,則可使用該關(guān)鍵字在用戶定義類型和其他類型之間進行隱式轉(zhuǎn)換,這篇文章就給大家詳細介紹implicit關(guān)鍵字做自定義類型隱式轉(zhuǎn)換的方法,需要的朋友可以參考下2015-08-08

