学习单例模式的笔记

单例模式 是常见的一种开发模式,如何在编程中实现唯一实例呢?

要想实现系统中只存在一个对应的实例,需要两个要素。

①创建实例需要调用构造方法,保证构造方法是私有的。

    这样就限制了在其他类中创建该类的对象的情况。即使该类不是密封类,

继承该类的子类中也无法创建父类对象和子类对象,因为在创建的时候需要

调用父类的构造方法,而私有的父类构造方法是子类调用不到的。

②静态方法或属性或只读字段返回该对象类型

既然在其他类中无法创建新的实例,唯一的实例只能在本类的定义中提供了。

这就需要一个静态的成员来保证在其他类中能获得该实例,否则就瞎菜了。

最简单的形式如:

class God
    {
        /// <summary>
        /// 私有构造函数
        /// </summary>
        private God()
        {
        }

        /// <summary>
        /// 通过静态属性
        /// </summary>
        public static God OnlyGod
        {
            //类内部可以调用构造方法
            get { return new God(); }
        }

        /// <summary>
        /// 或者通过方法返回
        /// </summary>
        /// <returns></returns>
        public static God ReturnonlyGod()
        {
            return new God();
        }

        /// <summary>
        /// 或者通过只读字段
        /// </summary>
        public static readonly God ReturnonlyGod = new God();
    }

 对于如果单例模式创建时需要参数的话,可以选择通过静态方法返回。

需要注意的是:这三种方法、属性或字段不能共存,否则就不是就单例实例了,而是双例模式、三例模式了。如下:

Console.WriteLine(ReferenceEquals(God.OnlyGod,God.ReturnonlyGod()));     //False

当然,这不是最标准的。一般的话,是需要定义一个私有的静态变量来作为单例的引用,所以常见的为

 public class God
    {
        /// <summary>
        /// 私有静态变量
        /// </summary>
        private static God _onlygod = null;

        /// <summary>
        /// 私有构造函数
        /// </summary>
        private God()
        {
        }
        /// <summary>
        /// 静态属性
        /// </summary>
        public static God OnlyGod
        {
            //_onlygod为空,则_onlygod = new God(),并返回
            //否则返回不为空的_onlygod
            get
            {
                return _onlygod ??(_onlygod = new God());
            }
        }
    }

也可以在私有的静态变量定义时直接new God()初始化。为了遵循缓式加载,还是用上面这个比较好。

 为了保证单例模式的实现,需要主要的几点:不要继承ICloneable(),不要支持序列化,不能对应多线程环境。

说:单例模式不能滥用,避免安全性问题,主要是考虑到多线程情况,多线程可能得到God类的多个实例

,就是说在平行宇宙中,世界上没有两片相同的叶子是不一定的。

所以要对单例模式进行一定的修订

通过 辅助变量+Double_Lock+Volatile

  public class God
    {
        /// <summary>
        /// 私有静态变量+volatile(保证编译顺序)
        /// </summary>
        private static volatile God _onlygod = null;

        /// <summary>
        /// +辅助对象
        /// </summary>
        private static object LockHelper = new object();

        /// <summary>
        /// 私有构造函数
        /// </summary>
        private God()
        {
        }
        /// <summary>
        /// 静态属性
        /// </summary>
        public static God OnlyGod
        {
            get
            {
                //+双检查
                if (_onlygod == null)
                {
                    lock (LockHelper)
                    {
                        if (_onlygod == null)
                        {
                            _onlygod = new God();
                        }
                    }
                }
                return _onlygod;
            }
        }
    }

摘抄总结:单例模式设计的核心是为了控制用户使用new对一个类的实例构造器的任意调用。

下面链接到,方便理解对于静态成员,加载的时候会初始化成员
新链接
静态构造函数相比静态初始化器相比,其优点是可以捕获异常,因为静态构造函数和静态初始化器出错时,CLR将会终止你的程序,而可以捕获异常的静态构造函数就可以使程序继续运行,但其缺点也在此,静态构造函数只能初始化一次,若出现错误造成某个类型没有初始化,那么CLR将不会再次进行初始化尝试。
原文地址:https://www.cnblogs.com/wwkk/p/4712234.html