• [白话设计模式] Singleton


    现实生活中有很多唯一的概念,如: 一个联合国秘书长,一个中国,一夫一妻制等等,多了怕要出问题.

    我们知道对象都是New出来的,要保证对象的唯一关键在于控制对象的创建权.所谓只允许官家放火,不许百姓点灯.官家只有一个,可以负责创建,要是随随便便让百姓点把火,怕是到处要遭火灾了.

    public class Singleton
    {
        private Singleton() {}
    }

    保证了类不能被client创建.那问题来了,client怎么访问呢,官方负责创建,并提供访问的入口.

    private static Singleton m_instance = new Singleton();
    public static Singleton Instance
    {
        get { return m_instance; }
    }

    此为"饿汉式单例类",因为此类一般加载就会调用类的静态构造函数,创建了类的实例.

    相比有"懒汉式单例类",

    public class Singleton
    {
        private static Singleton m_instance = null;
        private Singleton() { }
        public static Singleton Instance
        {
            get
            {
                if (m_instance == null)
                    m_instance = new Singleton();
                return m_instance;
            }
        }
    }

    改进的地方在于延迟了类的创建,但相比"饿汉式单例类"确有致命弱点,存在线程安全问题.编译器能够保证静态构造函数只被调用一次,所以"饿汉式单例类"是没有这个问题的.

    改进方法很简单,加个锁.

    private static object m_locker = new object();

    get
    {
        lock (m_locker)
        {
        if (m_instance == null)
            m_instance = new Singleton();
        return m_instance;
    }

    注意此锁对象必须为static,因为要保证在调用Instance方法前,此对象就被创建完毕.

    有人说,这样不是类在加载的时候也需要创建了一个静态变量实例吗.对,你观察的很仔细,但是你要知道一个object实例对象的创建一般要比Singleton实例的创建开销小的多.

    此加锁方法仍然存在严重的性能问题,要知道Singleton创建只有一次,但却可能被多线程频繁访问,访问一下加一下锁,怎么能保证并发访问的效率呢?

    这时候双重锁,派上了用场了.

    if (m_instance == null)
    {
        lock (m_locker)
        {
            if (m_instance == null)
                m_instance = new Singleton();
        }
    }
    return m_instance;

    这样就是一个比较完美的解决方案了,既做到了延迟创建,又保证了多线程安全,同时也保证了效率.只有第一次对象为null时,要加次锁,开销不大.

    最后要注意的地方就是在lock段里面还是要判断m_instance是否为null,要不然在并发的时候还是能创建多个对象的哦.

    实际应用:

    经常应用于读取配置文件啥的,一些Manager类啥的

    和工厂模式一起使用,class loader等

    Remoting Server激活方式有种就是Singleton

    参考

    阎宏,《Java与模式》

    Terrylee .NET设计模式(2):单件模式(Singleton Pattern)

  • 相关阅读:
    关注底层:IL部分
    腾讯与敏捷开发(zz)
    关于腾讯敏捷框架TAPD (ZZ)
    最新苹果官方iphone sdk 与 xcode 下载网址汇总
    松山湖之行
    [zz]在C#程序中实现插件架构
    华为与敏捷(zz)
    OK6410 tftp下载内核、文件系统以及nand flash地址相关整理、总结
    T400换风扇解决开机fan error问题
    校园故事一个非典型工科男的电子设计之路(整理版)
  • 原文地址:https://www.cnblogs.com/anders06/p/796443.html
Copyright © 2020-2023  润新知