Singleton-单例模式

单例模式算得上是设计模式中最简单的模式,不过简单的单例模式也有不简单的地方。在系统运行中实现只存在唯一实例,就得使用单例模式,然后程序中缓存数据管理类、配置数据管理类都是此类需要存在唯一实例的,就像windows操作系统的资源管理器一样。

这里介绍两种方案,一种是使用双重判断支持泛型的方案,还有一种就是使用IODH(initialization-on-demand holder) 延迟加载单例模式,这种方案主要借助 静态成员来实现,不过不支持泛型。

直接上代码:

    public static class Singleton<T> where T : class
    {
        private static volatile T _instance;
        private static object _lock = new object();

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            Type type = typeof(T);
                            ConstructorInfo ctor;
                            ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                                          null, new Type[0], new ParameterModifier[0]);
                            _instance = (T)ctor.Invoke(new object[0]);
                        }
                    }
                }

                return _instance;
            }
        }
    }

    /// <summary>
    /// 性能最差
    /// </summary>
    public static class Singleton
    {
        private static class Storage<T> where T : class
        {
            internal static volatile T _instance;
        }

        private static object _lock = new object();

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
        public static T GetInstance<T>() where T : class
        {
            if (Storage<T>._instance == null)
            {
                lock (_lock)
                {
                    if (Storage<T>._instance == null)
                    {
                        Type type = typeof(T);
                        ConstructorInfo ctor;
                        ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                                      null, new Type[0], new ParameterModifier[0]);
                        Storage<T>._instance = (T)ctor.Invoke(new object[0]);
                    }
                }
            }
            return Storage<T>._instance;
        }
    }

    /// <summary>
    /// 性能最佳
    /// </summary>
    public class IODHSingletonWithInnerClass
    {
        private IODHSingletonWithInnerClass()
        {

        }

        private static class HolderClass
        {
            public static readonly IODHSingletonWithInnerClass instance = new IODHSingletonWithInnerClass();
        }

        public static IODHSingletonWithInnerClass GetInstance()
        {
            return HolderClass.instance;
        }
    }

    public class IODHSingletonWithoutInnerClass
    {
        private IODHSingletonWithoutInnerClass()
        {

        }

        private static readonly IODHSingletonWithoutInnerClass instance = new IODHSingletonWithoutInnerClass();


        public static IODHSingletonWithoutInnerClass GetInstance()
        {
            return instance;
        }
    }
            int Maximum = 1000000;
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < Maximum; i++)
            {
                SoruceManager soruceManager1 = Singleton.GetInstance<SoruceManager>();
            }
            sw.Stop();
            long timeUsedFirstWay = sw.ElapsedTicks;
            sw = Stopwatch.StartNew();
            for (int i = 0; i < Maximum; i++)
            {
                SoruceManager soruceManager1 = Singleton<SoruceManager>.Instance;
            }
            sw.Stop();
            long timeUsedSecondWay = sw.ElapsedTicks;
            sw = Stopwatch.StartNew();
            for (int i = 0; i < Maximum; i++)
            {
                IODHSingletonWithoutInnerClass singleton = IODHSingletonWithoutInnerClass.GetInstance();
            }
            sw.Stop();
            long timeUsedThirdWay = sw.ElapsedTicks;
            sw = Stopwatch.StartNew();
            for (int i = 0; i < Maximum; i++)
            {
                IODHSingletonWithInnerClass singleton = IODHSingletonWithInnerClass.GetInstance();
            }
            sw.Stop();
            long timeUsedFourthWay = sw.ElapsedTicks;

            MessageBox.Show(string.Format("Singleton.GetInstance<SoruceManager>() 执行{0}次花费:{1}。\r\nSingleton<SoruceManager>.Instance执行{0}次花费:{2}。\r\nIODHSingletonWithoutInnerClass.GetInstance()执行{0}次花费:{3}。\r\nIODHSingletonWithInnerClass.GetInstance()执行{0}次花费:{4}。",Maximum, timeUsedFirstWay,timeUsedSecondWay,timeUsedThirdWay,timeUsedFourthWay));

使用上面的代码进行多次测试,发现使用IODH方案性能最佳,是否使用内部类差异性不大。

posted @ 2021-11-18 14:56  业荒于嬉  阅读(39)  评论(0编辑  收藏  举报