定義與特點
單例(Singleton)模式的定義:指一個類只有一個實例,且該類能自行創建這個實例的一種模式。
例如,Windows 中只能打開一個任務管理器,這樣可以避免因打開多個任務管理器窗口而造成內存資源的浪費,或出現各個窗口顯示內容的不一致等錯誤。
單例模式有 3 個特點:
- 單例類只有一個實例對象;
- 該單例對象必須由單例類自行創建;
- 單例類對外提供一個訪問該單例的全局訪問點;
結構與實現
單例模式是設計模式中最簡單的模式之一。通常,普通類的構造函數是公有的,外部類可以通過“new 構造函數()”來生成多個實例。但是,如果將類的構造函數設為私有的,外部類就無法調用該構造函數,也就無法生成多個實例。這時該類自身必須定義一個靜態私有實例,並向外提供一個靜態的公有函數用於創建或獲取該靜態私有實例。
單例模式的結構
單例模式的主要角色如下:
- 單例類(Singleton):包含一個實例且能自行創建這個實例的類。
- 訪問類(Client):使用單例的類。
單例模式的實現
Singleton 模式通常有兩種實現形式:懶漢式單例、餓漢式單例。
第 1 種:懶漢式單例
該模式的特點是類加載時沒有生成單例,只有當第一次調用 Getlnstance 方法時才去創建這個單例。代碼如下:
/// <summary>
/// 單例模式的實現-懶漢式單例
/// </summary>
public class Singleton
{
// 定義一個靜態變量來保存類的實例
private static Singleton instance;
// 定義一個標識確保線程同步
private static readonly object locker = new object();
// 定義私有構造函數,使外界不能創建該類實例
private Singleton(){ }
/// <summary>
/// 定義公有方法提供一個全局訪問點,同時你也可以定義公有屬性來提供全局訪問點
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
// 如果類的實例不存在則鎖定創建過程,否則直接返回
if (instance == null)
{
lock (locker)
{
// 如果類的實例不存在則創建,否則直接返回
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
第 2 種:餓漢式單例
該模式的特點是類一旦加載就創建一個單例,保證在調用 GetInstance 方法之前單例已經存在了。代碼如下:
/// <summary>
/// 單例模式的實現-餓漢式單例
/// </summary>
public class Singleton
{
// 定義一個靜態變量來保存類的實例
private static Singleton instance=new Singleton();
// 定義私有構造函數,使外界不能創建該類實例
private Singleton() { }
/// <summary>
/// 定義公有方法提供一個全局訪問點,同時你也可以定義公有屬性來提供全局訪問點
/// </summary>
/// <returns></returns>
public static Singleton GetInstance()
{
return instance;
}
}
應用場景
前面分析了單例模式的結構與特點,以下是它通常適用的場景的特點:
- 在應用場景中,某類只要求生成一個對象的時候,如一個班中的班長、每個人的身份證號等。
- 當對象需要被共享的場合。由於單例模式只允許創建一個對象,共享該對象可以節省內存,並加快對象訪問速度。如 Web 中的配置對象、數據庫的連接池等。
- 當某類需要頻繁實例化,而創建的對象又頻繁被銷毀的時候,如多線程的線程池、網絡連接池等。
擴展:多例模式
單例模式可擴展為多例(Multition)模式,這種模式可生成多個實例並保存在 List 中,客戶需要時可隨機獲取,其結構圖如圖所示:
多例模式可分為以下兩種:
- 有上限多例模式:多例類的實例數目有上限,並把實例的上限當做邏輯的一部分創造到了多例類的內部,這種多例模式叫做有上限多例模式。
- 無上限多例模式:多例類的實例數目並不需要有上限,實例數目並沒有上限的多例模式就叫做無上限多例模式。