單例模式是軟件工程中最著名的模式之一。從本質上講,單例是一個只允許創建自身的單個實例的類,通常可以簡單地訪問該實例。最常見的是,單例在創建實例時不允許指定任何參數 - 否則對實例的第二個請求但具有不同的參數可能會有問題!(如果對於具有相同參數的所有請求,應訪問相同的實例,則工廠模式更合適。)本文僅處理不需要參數的情況。通常,單例的要求是它們是懶惰地創建的 - 即在第一次需要之前不創建實例。
總結 Singleton 模式有兩個特點
- 單一實例 (Single Instance)
- 延遲建立實例 (Lazy Instantiation)
C# 實作
在C#中實現單例模式有各種不同的方法。從最常見的,不是執行緒安全的,以及完全延遲加載,安全,簡單且高性能的版本開始。
而有此共同特徵:
- 單個構造函數,它是私有且無參數的。這可以防止其他類實例化它(這將違反模式)。(C#來說類別必須
sealed
,且 建構式為private
) - 一個靜態變量,用於保存對單個已創建實例的引用。(C# 來說需要一個
public
與statc
的 ) - 公共靜態意味著獲取對單個創建實例的引用,必要時創建一個實例。(C# 來說類別需
public
與static
)
非執行緒安全 Singleton
這是個不好的案例,此方式不是執行緒安全,無法確保在多執行緒情況下是唯一的實例。
1 | public sealed class NotThreadSafeSingleton |
簡單執行緒安全 Singleton
使用 Lock 來確保執行緒安全。
1 | private static readonly object padlock = new object(); |
使用 Double-checked Locking 確保執行緒安全
使用 Double-checked Locking 確保執行緒安全。
1 | public sealed class DoubleCheckedLockingSingleton |
不使用 Lock, 確保執行緒安全 (非 Lazy)
此範例沒有使用 Lock, 而仍是執行緒安全的 Singleton,但不是 Lazy。
1 | public sealed class EagerSingleton |
完整 Lazy 實例
此範例達成了延遲建立。
1 | public sealed class LazySingleton |
使用 .NET 4 的 Lazy<T>
此方式使用後 .Net Framework 4 之後提供的 Lazy<T>,如此可以簡單的達成 Singleton 要求的 唯一
與 延遲建立
。
1 | public sealed class DotNet4LazySingleton |
結語
除了第一個範例不建議之外,其餘的是可以依實際情況斟酌使用。