• 单例模式(饿汉式和懒汉式)


    单例模式的定义


     

    对系统中的某些类来说,只有一个实例很重要。例如游戏中Player角色类,玩家角色必须唯一。定义全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。为了解决该问题,提出了让类自身负责保存它唯一实例。这个类保证没有其他实例被创建,并提供一个访问该实例的方法,这就是单例模式的思路。

    单例模式(Singleton Pattern)确保某一个类只有一个实例,而自行实例化并向整个系统提供这个实例,这个类被称为单例类,它提供全局访问的方法。它是一种对象创建型模式。

    • 单例类只能有一个实例
    • 单例类必须自行创建这个实例
    • 单例类必须自行向整个系统提供这个实例

    模式结构


     

    单例模式实现过程必须:

    • 单例类构造函数为私有
    • 提供一个自身的静态私有变量
    • 提供一个公有的静态工厂方法

    结构如下:

    单例模式的缺点


     

    1. 单例模式没有抽象层,很难对其扩展
    2. 单例类职责过重,违背了“”单一职责原则“”

     饿汉式和懒汉式


    1.饿汉式

    class  Singleton
    {
        private static Singleton _instanceSingleton = new Singleton();
    
        private Singleton()
        {
        //私有构造
        }
    
        public static Singleton getInstance()
        {
            return _instanceSingleton;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Singleton XiaoHua  = Singleton.getInstance();
        }
    }   

    2、懒汉式

     1 class  Singleton
     2 {
     3     private static Singleton _instanceSingleton;
     4 
     5     private Singleton()
     6     {//私有构造
     7     }
     8 
     9     public static Singleton getInstance()
    10     {
    11         if (_instanceSingleton ==null)
    12         {
    13          _instanceSingleton = new Singleton();
    14         }
    15         return _instanceSingleton;
    16     }
    17 }
    18 class Program
    19 {
    20     static void Main(string[] args)
    21     {
    22         Singleton XiaoHua  = Singleton.getInstance();
    23     }
    24 }        


    比较上面两种写法:

    从效率上看:

    一个判断一个不判断,判断的浪费时间,但节省空间。不判断的浪费空间,但节省时间。从某种角度优先考虑使用饿汉式。

    懒汉式是牺牲时间,也就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间。

    饿汉式选择牺牲空间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。

    从线程安全上看:

    不加同步的懒汉式是线程不安全的。假设有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,那就可能导致并发问题,出现两个实例。解决方法可以通过双重检查锁定(Double-CheckLocking)的双重判断机制。

    1. 当实例不存在且同时有两个线程调用GetInstance()方法时,它们都可以通过第一重“_instanceSingleton == null”判断
    2. 然后由于lock锁定机制,只有一个线程进入lock中执行创建代码,另一个线程处于排队等待状态
    3. 必须等待第一个线程执行完毕后才可以进入lock锁定的代码
    4. 进行第二重“_instanceSingleton == null”判断,是否创建实例

    最终改良后的懒汉式:

    class Singleton
    {
        private static Singleton _instanceSingleton;
            
        //程序运行时创建一个静态只读的辅助对象  
        private static readonly object syncRoot = new object();
    
    
        private Singleton()
        {//私有构造
        }
    
        public static Singleton getInstance()
        {
            if (_instanceSingleton == null)
            {
                lock (syncRoot)//线程控制
                {
                    if(_instanceSingleton == null){
                    
                    _instanceSingleton = new Singleton();                
                    
                    }      
                }
            }
            return _instanceSingleton;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Singleton XiaoHua = Singleton.getInstance();
        }
    }        
  • 相关阅读:
    机器学习(八) 多项式回归与模型泛化(上)
    机器学习(七) PCA与梯度上升法 (下)
    机器学习(七) PCA与梯度上升法 (上)
    机器学习(六) 梯度下降法 (下)
    机器学习(六) 梯度下降法 (上)
    机器学习(五) 线性回归法 (下)
    机器学习(五) 线性回归法 (上)
    机器学习(四) 机器学习(四) 分类算法--K近邻算法 KNN (下)
    获取字符串中img标签的url集合(转载)
    微信上传文章素材—ASP.NET MVC从View层传数据到Controller层
  • 原文地址:https://www.cnblogs.com/craft0625/p/7253059.html
Copyright © 2020-2023  润新知