1. 程式人生 > 實用技巧 >建立型模式之單例模式

建立型模式之單例模式

定義與特點

單例(Singleton)模式的定義:指一個類只有一個例項,且該類能自行建立這個例項的一種模式
例如,Windows 中只能開啟一個工作管理員,這樣可以避免因開啟多個工作管理員視窗而造成記憶體資源的浪費,或出現各個視窗顯示內容的不一致等錯誤。

單例模式有 3 個特點:

  • 單例類只有一個例項物件;
  • 該單例物件必須由單例類自行建立;
  • 單例類對外提供一個訪問該單例的全域性訪問點;

結構與實現

單例模式是設計模式中最簡單的模式之一。通常,普通類的建構函式是公有的,外部類可以通過“new 建構函式()”來生成多個例項。但是,如果將類的建構函式設為私有的,外部類就無法呼叫該建構函式,也就無法生成多個例項

。這時該類自身必須定義一個靜態私有例項,並向外提供一個靜態的公有函式用於建立或獲取該靜態私有例項。

單例模式的結構

單例模式的主要角色如下:

  • 單例類:包含一個例項且能自行建立這個例項的類。
  • 訪問類:使用單例的類。

2. 單例模式的實現

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 中,客戶需要時可隨機獲取,其結構圖如圖所示:

多例模式可分為以下兩種:

  • 有上限多例模式:多例類的例項數目有上限,已經把例項的上限當做邏輯的一部分,並創造到了多例類的內部,這種多例模式叫做有上限多例模式。
  • 無上限多例模式:多例類的例項數目並不需要有上限,例項數目並沒有上限的多例模式就叫做無上限多例模式。