跟我一起学23种经典设计模式——单例模式

         让我们一起开启设计模式吧!笔者以后会不定时更新我学习设计模式的随笔,一些重要的要点我都直接写在代码的注释里,好了,废话不多说,让我们从单例模式开始吧!

一、单线程下实例唯一

namespace SingletonPattern
{
    /// <summary>
    /// 这种的单例模式只能保证在单线程内实例唯一
    /// </summary>
    public class SingletonOnlyInOneThread
    {
        private static SingletonOnlyInOneThread _instance;
        private SingletonOnlyInOneThread() { }
        public static SingletonOnlyInOneThread Instance//这里作为一个属性来获取
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new SingletonOnlyInOneThread();
                }
                return _instance;
            }
        }
    }
}

二、多线程下实例唯一

namespace SingletonPattern
{
    /// <summary>
    /// 在多线程内保证实例唯一
    /// </summary>
    public class SingletonInMultiThread
    {
        private static volatile SingletonInMultiThread _instance;//volatile关键字保证实例在多个线程中同步,即在一个线程内对象内部发生了变化,其它线程内的对象也发生相应的变化
        private static object objectHelper = new object();//帮助对象,用于lock语句
        private SingletonInMultiThread() { }
        public SingletonInMultiThread Instance
        {
            get
            {
                if(_instance ==null)
                {
                    lock (objectHelper )//lock关键字使得同一时间内只能有一个线程进入语句块,其它线程必须等待
                    {
                        if (_instance == null)//这里使用的double check来确保在进入lock语句块后还未实例化对象
                        {
                            _instance = new SingletonInMultiThread();
                        }
                    }
                }
                return _instance;
            }
        }
    }
}

三、实现多线程下实例唯一的简单方式

namespace SingletonPattern
{
    /// <summary>
    ///保证实例在多线程内唯一的一种简单实现方式 
    /// </summary>
    public sealed class SingletonInMultiThreadWithEasyWay
    {
        public static readonly SingletonInMultiThreadWithEasyWay Instance = new SingletonInMultiThreadWithEasyWay();
        private SingletonInMultiThreadWithEasyWay() { }
    }
}

用reflector反编译后变成:
public sealed class SingletonInMultiThreadWithEasyWayCompile
    {
        public static readonly SingletonInMultiThreadWithEasyWayCompile Instance;
        static SingletonInMultiThreadWithEasyWayCompile ()//一个静态的构造函数
        {
            Instance = new SingletonInMultiThreadWithEasyWayCompile();
        }
        private SingletonInMultiThreadWithEasyWayCompile() { }
    }
这样的实现可以自动帮我们加锁实现多线程实例唯一,
但如果我们如果以这种实现的话,这样会带来的一个问题就是无法实现有参构造函数的单例,因为静态构造函数不允许带参数,解决方法:使用属性或方法在得到实例后进行初始化对象,比如:
public sealed class SingletonInMultiThreadWithEasyWayCompile
    {
        public static readonly SingletonInMultiThreadWithEasyWayCompile Instance;
        static SingletonInMultiThreadWithEasyWayCompile ()//一个静态的构造函数
        {
            Instance = new SingletonInMultiThreadWithEasyWayCompile();
        }
        private SingletonInMultiThreadWithEasyWayCompile() { }
        public int Property1 { get; set; }
        public int Property2 { get; set; }
        public void Init(int property1, int property2)
        {
            this.Property1 = property1;
            this.Property2 = property2;
        }
    }
原文地址:https://www.cnblogs.com/luoweihui/p/3271326.html