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

   今天我们来说说在编程时候我们最常见也是最好用的一种单例模式 。单例模式太简单了,让一个类变成只有一个唯一的对象类,方便客户对象调用。那这有什么好说的呢,我们先来看看一个普通的单例模式代码。

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值