面试算法(二)实现Singleton模式

来源:互联网 发布:淘宝个人中心在哪 编辑:程序博客网 时间:2024/06/04 19:43

1、设计一个类,我们只能生成该类的一个实例。

解法一:由于只能生成一个实例,因此必须把构造函数设为私有函数以禁止他人创建实例。我们可以定义一个静态的实例,在需要的时候创建该实例。

public sealed class Singleton1{    private Singleton1()    {    }    private static Singleton1 instance = null;    public static Singleton1 Instance    {         get         {              if(instance == null)                  instance = new Singleton1();              return instance;          }    }}
上述代码在Singleton1的静态属性Instance中,只有在instance为null的时候才创建一个实例以避免重复创建。同时我们把构造函数定义为私有函数,这样能确保只创建一个实例。

但如果有两个线程同时运行到判断instance是否为null的if语句,并且instance的确没有创建时,那么两个线程都会创建一个实例,此时类型Singleton1就不再满足单例模式的要求了。


解法二:加一个同步锁。假设有两个线程同时想创建一个实例,由于在一个时刻只有一个线程能得到同步锁,另一个只能等待。但锁是很耗时的操作。

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

解法三:加同步锁前后两次判断实例是否已存在。

public sealed class Singleton3{    private Singleton3()    {     }     private static object syncObj = new object();     private static Singleton3 instance = null;     public static Singleton3 Instance     {          get          {              if(instance == null)              {                  lock(syncObj)                  {                     if(instance == null)                         instance = new Singleton3();                   }                }              return instance;           }        }}


Singleton3中只有当instance为null即没有创建时,需要加锁操作。当instance已经创建出来之后,则无须加锁。因为只在第一次的时候instance为null,因此只在第一次试图创建实例的时候需要加锁。


推荐解法一:利用静态构造函数

C#的静态构造函数能确保只调用一次,在此时初始化静态变量。

public sealed class Sinleton4{   private Singleton4()   {   }    private static Singleton4 instance = new Singleton4();     public static Singleton4 Instance     {         get         {            return instance;          }       }}
在Singleton4中,实例instance并不是第一次调用属性Sinleton4.Instance的时候创建,而是在第一次用到Singleton4的时候就会被创建。


推荐解法二:实现按需创建实例

public sealed class Sinleton5{   Singleton5()   {   }    public static Singleton5 Instance    {         get         {            return Nested.instance;          }     }      class Nested      {           static Nested()           {            }            internal static readonly Singleton5 instance = new Singleton5();       }}

当我们第一次试图通过属性Singleton5.Instance得到Singleton5的实例时,会自动调用Nested的静态构造函数创建实例instance。如果我们不调用属性Singleton5.Instance,那么就不会触发.NET运行时调用Nested,也不会创建实例,真正做到了按需创建。










0 0