• 设计模式—单例模式


    单例模式主要特点不是根据客户程序调用生成一个新的实例,而是控制某个类型的实例数量唯一一个。即单例模式就是保证在整个应用程式的生命周期中,在任何时刻,被知道的类只有一个实例,并为客户程序提供一个获取该实例的全景访问点

    一.经典模式

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        public class Instance
        {
            //经典模式
            private static Instance instance;
            private Instance()
            {
    
            }
            public static Instance GetInstance()
            {
                if (instance == null)
                {
                    instance = new Instance();
                }
                return instance;
            }      
        }
    }
    

     解释:在经典模式下,没有考虑多线程并发获取实例的问题,即有可能出现两个线程同时获取实例,且此时为null时,会出现两个线程创建了两个实例,违反了单例模式的规则。

    二.多线程下的单例模式

     1.Lazy(懒汉) 模式

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        public class Instance
        {
            //Lazy(懒汉)模式
            private static Instance instance;
            private static object _lock = new object();
            private Instance()
            {
    
            }
            public static Instance GetInstance()
            {
                if (instance == null)
                {
                    lock (_lock)
                    {
                        if (instance == null)
                        {
                            instance = new Instance();
                        }
                    }
                }
                return instance;
            }    
        }
    }

    解释:上述代码使用双重锁定方式较好的解决了多线程下的单例模式实现,先看内层的if语句块,使用这个语句块时,先进行加锁操作,保证只有一个线程可以访问该语句块,进而保证只创建了一个实例。再看外层的if语句块,这使得 每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,节省了性能开 销。两次判断Instance==null是第二个是为了万一一个线程刚锁定时,已经有一个线程实例了一个Instance,此时如果不判断会又实例一个

    2.饿汉模式(特点:自己主动实例)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        public class Instance
        {
            private static readonly Instance instance = new Instance();
            private Instance() { }
            public static Instance GetInstance() {
                return instance;
            }
        }
    }

    解释:上面使用的readonly关键可以跟static一起使用,用于指定该常量是类别级的,它的初始化交由静态构造函数实现,并可以在运行时编译。在这种模 式下,无需自己解决线程安全性问题,CLR会给我们解决。由此可以看到这个类被加载时,会自动实例化这个类,而不用在第一次调用 GetInstance()后才实例化出唯一的单例对象。

    不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

  • 相关阅读:
    Java实现 LeetCode 173 二叉搜索树迭代器
    PHP array_reverse() 函数
    PHP array_replace_recursive() 函数
    PHP array_replace() 函数
    PHP array_reduce() 函数
    PHP array_rand() 函数
    C# 通配符转正则
    win10 uwp 验证输入 自定义用户控件
    win10 uwp 验证输入 自定义用户控件
    win10 uwp 验证输入 自定义用户控件
  • 原文地址:https://www.cnblogs.com/xishuqingchun/p/3909562.html
Copyright © 2020-2023  润新知