zoukankan      html  css  js  c++  java
  • 学习单例模式的笔记

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

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

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

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

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

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

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

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

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

    最简单的形式如:

    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将不会再次进行初始化尝试。
  • 相关阅读:
    javascript模块化进阶
    javascript模块化基础
    css架构探索
    javascript函数基础概念 (补充完结)
    聊聊圣杯布局
    javascript函数基础概念
    yum提示This system is not registered with RHN.RHN support will be disabled.
    Linux分区和挂载硬盘
    Thunderbird扩展
    yum install nginx
  • 原文地址:https://www.cnblogs.com/wwkk/p/4712234.html
Copyright © 2011-2022 走看看