设计模式之单例模式

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

class Singleton
{
    private static Singleton instance;
      
    private Singleton()
    {
        
    }

    public static Singleton GetInstance()
    {
        if(instance==null)
        {
            instance=new Singleton();
        }

        return instance;
    }
}                    

多线程下的单例模式

上面的写法如果在多线程的情况下可能会出现同时访问Singleton类中的GetInstance()方法,就会造成创建多个实例的情况。

为了解决以上问题,可以给进程一把锁来处理。这里用到的是lock语句,lock是确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程视图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

class Singleton
{
      private static Singleton instance;

      private static readonly object syscRoot=new objiec();   //程序运行时创建一个静态只读的进程辅助对象

      private Singleton()
      {

      }

      public static Singleton GetInstance()
      {
          lock(syscRoot)  //在同一个时刻加了锁的那部分程序只有一个线程可以进入
          {
              if(instance==null)
              {
                  instance=new Singleton();
              }
          }

          return instance;
      }                
}                

以上方法每次调用时都要lock一次,这样就会影响性能,改进如下:

class Singleton
{
      private static Singleton instance;

      private static readonly object syscRoot=new objiec();   //程序运行时创建一个静态只读的进程辅助对象

      private Singleton()
      {

      }

      public static Singleton GetInstance()
      {
          if(instance==null)
          {
              lock(syscRoot)  //在同一个时刻加了锁的那部分程序只有一个线程可以进入
              {
                  if(instance==null)
                  {
                      instance=new Singleton();
                  }
              }
          }

          return instance;
      }                
}      

这样的话,就不会线程每次都加锁,而只有在实例未被创建的时候在加锁处理,这种做法成为双重锁定。

静态初始化简化单例模式

public sealed class Singleton         //sealed阻止了反生派生,而派生可能会增加实例
{
    private static readonly Singleton instance=new Singleton();   //在第一次引用类的任何成员时创建实例,
        
    private Singleton(){}
  
    public static Singleton GetInstance()
    {
         return instance;   
    }
}    

注意:instance变量标记为readonly,这意味着只能在静态初始化期间或类构造函数中分配变量。

由于这种静态初始化的方法是在自己被加载时就将自己实例化,所以被形象地称为饿汉式单例类,原来的要在第一次被引用时才会将自己实例化,所以就被称为懒汉式单例类。

以上所写都是参考《大话设计模式》

posted @ 2013-06-11 17:11  蓦然浩怪  阅读(252)  评论(0编辑  收藏  举报