1. 程式人生 > >Singleton單件模式C#版

Singleton單件模式C#版

目錄

單執行緒

靜態屬性

靜態構造器

多執行緒  

測試


有時候需要在程式中保證一個類只能有一個例項,並且提供一個該例項的全域性訪問點,這時候就需要利用單件模式。所有的程式碼是在控制檯應用中可以執行的。

單執行緒

靜態屬性

用靜態屬性和私有構造器來實現單例模式,靜態屬性確保全域性只有一個例項,私有構造器確保外部無法構造該類例項,通過對靜態屬性的第一次訪問,建立該類的一個例項,以後所有的對屬性的訪問都是對該例項的訪問。

靜態構造器

class Singleton
{
    public static readonly Singleton Instance = new Singleton();

    private Singleton()
    {
    }
}

靜態構造器不僅支援單執行緒,也支援多執行緒。上述欄位初始化方式稱為內聯初始化,等效於下述程式碼。

class Singleton
{
    public static readonly Singleton Instance;

    static Singleton()
    {
        Instance = new Singleton();
    }

    private Singleton()
    {

    }
}

多執行緒  

多執行緒情況下,假設執行緒1和2同時第一次訪問Singleton.Instance,那麼執行緒1就會新建一個例項,與此同時,執行緒2也會新建一個例項,因此,為了確保執行緒安全,我們需要設定執行緒同步鎖。這裡,設定雙重保障,用volatile關鍵字保證編譯器在編譯過程中不會對程式碼進行調整,同步鎖lockHelper保證不會有兩個執行緒同時訪問instance欄位。

class Singleton
{
    private static volatile Singleton instance;
    private static object lockHelper = new object();

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockHelper)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

    private Singleton()
    {
    }
}

測試

這裡測試一下是否實現我們的單例模式,Object.GetType()函式返回的是類名稱,為了比較兩個例項是否相同,需要用到反射,具體來說使用System.Object.ReferenceEquals函式,具體程式碼如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SingletonMode
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton t1 = Singleton.Instance;
            Singleton t2 = Singleton.Instance;
            Console.WriteLine("t1和t2型別" + t1.GetType().ToString());
            Console.Write("t1和t2型別是否相等:");
            Console.WriteLine(t1.GetType() == t2.GetType());
            Console.Write("t1和t2例項是否相等:");
            Console.WriteLine(System.Object.ReferenceEquals(t1, t2));
            Console.WriteLine("\n");

            Student s1 = new Student();
            Student s2 = new Student();
            Console.WriteLine("s1和s2型別" + s1.GetType().ToString());
            Console.Write("s1和s2型別是否相等:");
            Console.WriteLine(s1.GetType() == s2.GetType());
            Console.Write("s1和s2例項是否相等:");
            Console.WriteLine(System.Object.ReferenceEquals(s1, s2));

            Console.ReadKey();
        }
    }

    
}
class Singleton
{
    public static readonly Singleton Instance;

    static Singleton()
    {
        Instance = new Singleton();
    }

    private Singleton()
    {

    }
}

class Student
{

}


程式碼輸出結果

t1和t2型別Singleton
t1和t2型別是否相等:True
t1和t2例項是否相等:True


s1和s2型別Student
s1和s2型別是否相等:True
s1和s2例項是否相等:False