11.29.07

Implementing the Singleton Pattern in C#

發表於 C#, Programming Language 於 5:42 am 由 zusecheng

基本上 Singleton Pattern 可以有很多實作方法
Singleton Pattern 中比較重要的考量點有兩個

  • Thread Safe
  • Lazy Binding 

在C#中,最簡單的實作方式就是

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


Lazy Binding -  OK!
Thread safe  -   NO

如果為了滿足 Thread Safe

public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object objlock = new object();
    Singleton()
    {
    }
    public static Singleton Instance
    {
        get
        {
            lock (objlock)
            {
                if (instance==null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

Lazy Binding -  OK!
Thread safe  -   OK!

可惜它有一個很大的缺點 lock 的時間消耗是 if的好幾個數量級
接下來是使用OS中最普遍解法 double checking

    if (instance==null)
    {
                lock (objlock)
                {
                    if (instance==null)
                    {
                        instance = new Singleton();
                    }
                }
    }
    return instance;

當然 其實程式語言也可以很美 利用C#語言的特性

public sealed class Singleton
{
    static readonly Singleton instance = new Singleton();
    static Singleton(){}     Singleton(){}
    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

又簡短又正確 可惜它失去Lazy Binding 的能力
想加入Lazy Binding 需要作一些苦工

public sealed class Singleton
{
    Singleton(){}
    public static Singleton Instance
    {
        get {
            return SingletonPorvider.instance;
        }
    }
    class SingletonPorvider
    {
        static SingletonPorvider(){}          internal static readonly Singleton instance = new Singleton();
    }
}

最後 把他泛化

// NON Lazy Binding 版本

public class Singleton<T> where T : new()
{
    private static T instance = new T();
    static Singleton(){}
    Singleton(){}
    public static T Instance
    {
        get
        {
            return instance;
        }
    }
}

// Lazy Binding 版本

public class Singleton<T> where T : new()
{
    Singleton(){}
  public static T Instance
  {
   get
   {
    return SingletonPorvider.instance;
   }
  }
  class SingletonPorvider
  {
   static SingletonPorvider() { }
   internal static readonly T instance = new T();
  }
}