【設計模式】面向對象設計七大原則
【設計模式】設計模式概念和分類
【設計模式】創建型設計模式:單例模式
定義
單例模式(Singleton Pattern):單例模式確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例,這個類稱爲單例類,它提供全局訪問的方法。
單例模式的要點有三個:
(1)單例類只有一個實例;
(2)該單例實例必須由單例類自行創建;
(3)單例類對外提供一個訪問該實例的全局訪問點;
單例模式是一種對象創建型模式。單例模式又名單件模式或單態模式。
單例模式的結構
單例模式的目的是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。單例模式包含的角色只有一個,就是單例類——Singleton。單例類擁有一個私有構造函數,確保用戶無法通過new關鍵字直接實例化它。除此之外,該模式中包含一個靜態私有成員變量與靜態公有的工廠方法,該工廠方法負責檢驗實例的存在性並實例化自己,然後存儲在靜態成員變量中,以確保只有一個實例被創建。
在單例模式的實現過程中,需要注意如下三點:
(1)單例類的構造函數爲私有;
(2)提供一個自身的靜態私有成員變量;
(3)提供一個公有的靜態工廠方法。
單例模式的實現
單例模式有懶漢式和餓漢式兩種實現形式。
懶漢式(線程不安全)
該模式的特點是類加載時沒有生成單例,只有當第一次調用 GetInstance 方法纔去創建單例。
/// <summary>
/// Singleton class. Thread unsafe.
/// </summary>
public class Singleton
{
private Singleton() { }
private static Singleton _Instance = null;
/// <summary>
/// Get an instance of the Singleton class.
/// </summary>
public static Singleton GetInstance()
{
if (_Instance == null)
{
_Instance = new Singleton();
}
return _Instance;
}
}
將存在線程非安全的問題。在多線程、高併發的情況下,可能同時產生多個實例,違背了單例模式。
餓漢式(線程安全)
該模式的特點是類一旦加載就創建一個單例,保證在調用 GetInstance 方法之前單例已經存在了。
/// <summary>
/// Singleton class. Thread safety.
/// </summary>
public class Singleton
{
private Singleton() { }
// Instantiate yourself when you are loaded
private readonly static Singleton _Instance = new Singleton();
/// <summary>
/// Get an instance of the Singleton class.
/// </summary>
public static Singleton GetInstance()
{
return _Instance;
}
}
餓漢式單例在類創建的同時就已經創建好一個靜態的對象供系統使用,以後不再改變,以後線程安全的,可以直接用於多線程而不會出現問題。
懶漢式雙重鎖模式(線程安全)
保證多線程中只存在唯一實例
/// <summary>
/// Singleton class. Thread safety.
/// </summary>
public class Singleton
{
private Singleton() { }
private static Singleton _Instance = null;
private static readonly object sysLock = new object();
/// <summary>
/// Get an instance of the Singleton class
/// </summary>
public static Singleton GetInstance()
{
lock (sysLock)
{
if (_Instance == null)
{
_Instance = new Singleton();
}
}
return _Instance;
}
}
lock 關鍵字可以用來確保代碼塊完成運行,而不會被其他線程中斷。這是通過在代碼塊運行期間爲給定對象獲取互斥鎖來實現的。
泛型單例模式
對泛型類進行約束,T只能是一個Class,並且有一個公共無參構造函數
/// <summary>
/// Singleton base class. Thread safety.
/// </summary>
public abstract class Singleton<T> where T : class ,new()
{
private Singleton() { }
private static T _Instance = null;
private static readonly object sysLock = new object();
/// <summary>
/// Get an instance of the Singleton class
/// </summary>
public static T Instance
{
get
{
lock (sysLock)
{
if (_Instance == null)
{
_Instance = new T();
}
}
return _Instance;
}
}
}