zoukankan      html  css  js  c++  java
  • 设计模式-单例模式-创建型模式

    单例模式用于在整个软件系统当中保持唯一实例,在 C# 当中最能够体现此概念的就是静态类,静态类的生命周期是跟随整个程序,并且在整个程序中仅保有一个实例。

    不过在这里我们不再详细阐述单例模式与静态类有什么区别,如果有兴趣的话可以查看 这篇博文这篇博文

    这里说一下个人的理解:

    • 单例模式可以用实现接口与继承,而静态类是无法实现的。
    • 单例模式可以方便进行 Mock 测试。
    • 单例对象可以很方便的进行替换。
    • 静态类/静态方法更多的是用于工具类方法,是无状态的。

    为了保证我们的对象是全局唯一的,那么我们肯定不能够通过 new 来创建单例对象,所以我们首先要将其构造函数设为私有的,其次我们肯定要有一个 static 字段来保存我们唯一的实例化对象。
    既然不能通过 new 来实例化对象,则需要提供一个全局访问点。下面我们就来看一下具体实现:

    public class SingletonImplementation
    {
        private static SingletonImplementation m_instance;
        private SingletonImplementation(){}    
    
        public static SingletonImplementation GetInstance()
        {
            if(m_instance == null) m_instance = new SingletonImplementation();
            return m_instance;
        }
    }
    

    实现起来是相当简单的,这里我们将构造函数设置为私有的,然后通过 GetInstance 方法来取得对象的实例。其实这里可以改用一个静态属性来实现,更加方便。
    如果考虑到线程安全的话,就需要加一个 locker 来保证访问不会重复创建对象。因为如果在多线程环境当中调用这个静态类的时候,可能在同一时间都会访问到 m_instance,这个时候 m_instance 都为空的情况下就会连续创建两次实例,这就违背了初衷。最简单的方法就是加锁,让 m_instance 在同一时间只能一个线程访问这个对象。

    public class SingletonImplementation
    {
        private static SingletonImplementation m_instance;
        private static readony object _locker = new object();
        private SingletonImplementation(){}
    
        public static SingetonImplementation Instance
        {
            get
            {
                lock(_locker)
                {
                    if(m_instance == null) m_instance = new SingetonImplementation();
                }
                
                return m_instance;
            }
        }
    }
    

    不过这样又产生了另外一个问题,如果线程每次访问 Instance 都会对 _locker 加锁后在访问实例是否存在,这样对性能影响十分严重。这里我们可以使用 双重检查锁定模式 来实现。

    双重检查锁定模式(也被称为"双重检查加锁优化","锁暗示"(Lock hint)[1])
    是一种软件设计模式用来减少并发系统中竞争和同步的开销。双重检查锁定模式
    首先验证锁定条件(第一次检查),只有通过锁定条件验证才真正的进行加锁逻辑
    并再次验证条件(第二次检查)。

    也就是说我们首先验证 m_instance 是否为空,如果为空的话再进行加锁执行逻辑,否则的话直接返回已经实例化成功的 m_instance。

    public class SingetonImplementation
    {
        private static SingetonImplementation _instance;
        private static readonly object _locker = new object();
        private SingetonImplementation(){}
    
        public static SingetonImplementation Instance
        {
            if(_instance == null)
            {
                locker(_locker)
                {
                    if(_instance == null) _instance = new SingetonImplementation();
                }
            }
            
            return _instance;
        }
    }
    
  • 相关阅读:
    MPI 学习
    关于谱聚类
    线程调度的学习例子
    [转] Linux的IO复用
    网络编程socket
    关于python机器学习常用算法的例子
    [转](阿里笔试)使用多线程和sleep函数生成字符串的伪随机排列
    Single Number II
    阿里面试题,N个士兵的通话问题
    凸优化算法之牛顿法
  • 原文地址:https://www.cnblogs.com/myzony/p/8434268.html
Copyright © 2011-2022 走看看