單例模式就是保證在整個應用程序的生命周期中,在任何時刻,被指定的類只有一個實例,並為客戶程序提供一個獲取該實例的全局訪問點。
第一種:
因為靜態變量的生命周期跟整個應用程序的生命周期是一樣的,所以可以定義一個私有的靜態全局變量instance來保存該類的唯一實例;
必須提供一個全局函數訪問獲得該實例,並且在該函數提供控制實例數量的功能,即通過if語句判斷instance是否已被實例化,
如果沒有則可以同new創建一個實例;否則,直接向客戶返回一個實例。
在這種經典模式下,沒有考慮線程並發獲取實例問題,即可能出現兩個線程同時獲取instance實例,且此時其為null時,就會出現兩個線程分別創建了instance,違反了單例規則
private static Singleton instance = null; private Singleton() { } public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } }
第二種:
每次請求實例時都會獲得鎖定,因此性能會受到影響
private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { lock (padlock) { if (instance == null) { instance = new Singleton(); } return instance; } } }
第三種:
使用的readonly關鍵可以跟static一起使用,用於指定該常量是類別級的,它的初始化交由靜態構造函數實現,並可以在運行時編譯。在這種模式下,無需自己解決線程安全性問題,CLR會給我們解決。
由此可以看到這個類被加載時,會自動實例化這個類,而不用在第一次調用GetInstance后才實例化出唯一的單例對象。
private static readonly Singleton instance = new Singleton();
static Singleton() { } private Singleton() { } public static Singleton Instance { get { return instance; } }
第四種:
優雅寫法是要用到.net 4.0里Lazy<T>
public sealed class Singleton_Program
{
private static readonly Lazy<Singleton_Program> lazy = new Lazy<Singleton_Program>(() => new Singleton_Program());
public static Singleton_Program Instance { get { return lazy.Value; } }
private Singleton_Program()
{
}
}