设计模式深入学习-单例模式

来源:互联网 发布:aspx php混合网站 编辑:程序博客网 时间:2024/05/21 22:12
   今天我们来说说在编程时候我们最常见也是最好用的一种单例模式 。单例模式太简单了,让一个类变成只有一个唯一的对象类,方便客户对象调用。那这有什么好说的呢,我们先来看看一个普通的单例模式代码。

public class Singleton{    private static Singleton instance;     private Singleton() { }     public static Singleton Instance    {        get        {            if (instance == null)            {                instance = new Singleton();            }            return instance;        }    }}
  这个普通的单例模式,其实还是会有几个要点,我们先来看看
  Singleton 模式中的实例和构造器可以设置为protected以允许子类派生
  Singleton 模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
  Singleton 模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
  Singleton 模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。不能应对多线程环境:在多线程环境中,使用Singleton模式仍然有可能得到Singleton类的多个实例对象。

  上面就是单例模式的几个使用注意事项,也就是说,我们平时如果是这样写出来的单例模式其实是不安全的,不能保证在多线程下的唯一性。
  那怎么办呢,其实我们可以尝试修改成其他写法。


public class Singleton{    private static volatile Singleton instance=null;    private static object lockHelper = new object();    private Singleton() { }     public static Singleton Instance    {        get        {            if (instance == null)            {                lock (lockHelper)                {                    if (instance == null)                    {                        instance = new Singleton();                    }                 }            }            return instance;        }    }}
  现在我们重新修改了一遍,首先新添加了一个object类型的数据对象,然后每次在get单例的时候先检查是否为空,然后在锁住当前进程,然后再次检查,最后在new出这个单例。使用了Double Check 双层检查的方式,这样就能有效的避免了多线程环境下无法保证单例唯一性。对了, 我们在私有的instance中 在static后面还添加了volatile修饰符,这个修饰符的作用是可以保证程序不会对程序进行排序,微调。这样就可以严格的确保了对象构造的顺序。
  可能你会说,这样的单例是不是有点太麻烦,有没有更简单的办法?答案是有,下面我们来看最简单的一种:

public class Singleton{    public static readonly Singleton Instance = new Singleton();    private Singleton() { }}
  这次是不是更简单了呢, 这次简单的原因是使用了readonly 修饰符。单例模式的初始化由前面的static静态函数实现,然后在运行时编译,当这个类被加载的时候,会自动实例化这个类,就不用在后面调用get才实例化出唯一的对象了,而且无需我们关心线程安全性问题,底层会自动解决。但是小有小的好处,也不可避免带来一点麻烦,比如这样写的话就不支持构造器接受参数了,所以我们得小拆分下,让程序变得更灵活。
public class Singleton{    public static readonly Singleton Instance;    static Singleton()    {        Instance = new Singleton();    }     private Singleton() { }     }
 现在我们把new的那块代码拆分,留到构造器实例化重新生成,这样就可以使用重载来另外加带传参的方法了。
好了,这就是单例模式的一些小细节的处理,代码比较少,但是都比较实用,希望可以帮助到大家。


0 0