Singleton單件模式C#版
阿新 • • 發佈:2018-12-16
目錄
有時候需要在程式中保證一個類只能有一個例項,並且提供一個該例項的全域性訪問點,這時候就需要利用單件模式。所有的程式碼是在控制檯應用中可以執行的。
單執行緒
靜態屬性
用靜態屬性和私有構造器來實現單例模式,靜態屬性確保全域性只有一個例項,私有構造器確保外部無法構造該類例項,通過對靜態屬性的第一次訪問,建立該類的一個例項,以後所有的對屬性的訪問都是對該例項的訪問。
靜態構造器
class Singleton { public static readonly Singleton Instance = new Singleton(); private Singleton() { } }
靜態構造器不僅支援單執行緒,也支援多執行緒。上述欄位初始化方式稱為內聯初始化,等效於下述程式碼。
class Singleton
{
public static readonly Singleton Instance;
static Singleton()
{
Instance = new Singleton();
}
private Singleton()
{
}
}
多執行緒
多執行緒情況下,假設執行緒1和2同時第一次訪問Singleton.Instance,那麼執行緒1就會新建一個例項,與此同時,執行緒2也會新建一個例項,因此,為了確保執行緒安全,我們需要設定執行緒同步鎖。這裡,設定雙重保障,用volatile關鍵字保證編譯器在編譯過程中不會對程式碼進行調整,同步鎖lockHelper保證不會有兩個執行緒同時訪問instance欄位。
class Singleton { private static volatile Singleton instance; private static object lockHelper = new object(); public static Singleton Instance { get { if (instance == null) { lock (lockHelper) { if (instance == null) { instance = new Singleton(); } } } return instance; } } private Singleton() { } }
測試
這裡測試一下是否實現我們的單例模式,Object.GetType()函式返回的是類名稱,為了比較兩個例項是否相同,需要用到反射,具體來說使用System.Object.ReferenceEquals函式,具體程式碼如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SingletonMode
{
class Program
{
static void Main(string[] args)
{
Singleton t1 = Singleton.Instance;
Singleton t2 = Singleton.Instance;
Console.WriteLine("t1和t2型別" + t1.GetType().ToString());
Console.Write("t1和t2型別是否相等:");
Console.WriteLine(t1.GetType() == t2.GetType());
Console.Write("t1和t2例項是否相等:");
Console.WriteLine(System.Object.ReferenceEquals(t1, t2));
Console.WriteLine("\n");
Student s1 = new Student();
Student s2 = new Student();
Console.WriteLine("s1和s2型別" + s1.GetType().ToString());
Console.Write("s1和s2型別是否相等:");
Console.WriteLine(s1.GetType() == s2.GetType());
Console.Write("s1和s2例項是否相等:");
Console.WriteLine(System.Object.ReferenceEquals(s1, s2));
Console.ReadKey();
}
}
}
class Singleton
{
public static readonly Singleton Instance;
static Singleton()
{
Instance = new Singleton();
}
private Singleton()
{
}
}
class Student
{
}
程式碼輸出結果
t1和t2型別Singleton
t1和t2型別是否相等:True
t1和t2例項是否相等:True
s1和s2型別Student
s1和s2型別是否相等:True
s1和s2例項是否相等:False