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

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:58   2029   0

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 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP