zoukankan      html  css  js  c++  java
  • C#の单例模式

    版本一:

    /// <summary>
    /// A simple singleton class implements.
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton _instance = null;

        /// <summary>
        /// Prevents a default instance of the
        /// <see cref="Singleton"/> class from being created.
        /// </summary>
        private Singleton()
        {
        }

        /// <summary>
        /// Gets the instance.
        /// </summary>
        public static Singleton Instance
        {
            get { return _instance ?? (_instance = new Singleton()); }
        }
    }

          以上的实现方式适用于单线程环境,因为在多线程的环境下有可能得到Singleton类的多个实例。假如同时有两个线程去判断

    (null == _singleton),并且得到的结果为真,那么两个线程都会创建类Singleton的实例,这样就违背了Singleton模式“唯一实例”的初衷。

    版本二:

    /// <summary>
    /// A thread-safe singleton class.
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton _instance = null;
        private static readonly object SynObject = new object();
    
        Singleton()
        {
        }
    
        /// <summary>
        /// Gets the instance.
        /// </summary>
        public static Singleton Instance
        {
            get
            {
                // Syn operation.
                lock (SynObject)
                {
                    return _instance ?? (_instance = new Singleton());
                }
            }
        }
    }

            以上方式的实现方式是线程安全的,首先我们创建了一个静态只读的进程辅助对象,由于lock是确保当一个线程位于代码的临界区时,另一个线程不能进入临界区(同步操作)。如果其他线程试图进入锁定的代码,则它将一直等待,直到该对象被释放。从而确保在多线程下不会创建多个对象实例了。只是这种实现方式要进行同步操作,这将是影响系统性能的瓶颈和增加了额外的开销。

    版本三:

    /// <summary>
    /// Double-Checked Locking implements a thread-safe singleton class
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton _instance = null;
        // Creates an syn object.
        private static readonly object SynObject = new object();

        Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                // Double-Checked Locking
                if (null == _instance)
                {
                    lock (SynObject)
                    {
                        if (null == _instance)
                        {
                            _instance = new Singleton();
                        }
                    }
                }
                return _instance;
            }
        }
    }

    版本四:经典模式

    public class Singleton
    {
            private static Singleton instance;

            private Singleton()
            {
           
            }

            public static Singleton GetInstance()
            {
                    if(instance==null)
                    {
                            instance=new Singleton();
                    }
                    return instance;
            }
    }

      解析如下:

      1)首先,该Singleton的构造函数必须是私有的,以保证客户程序不会通过new()操作产生一个实例,达到实现单例的目的;

      2)因为静态变量的生命周期跟整个应用程序的生命周期是一样的,所以可以定义一个私有的静态全局变量instance来保存该类的唯一实例;

      3)必须提供一个全局函数访问获得该实例,并且在该函数提供控制实例数量的功能,即通过if语句判断instance是否已被实例化,如果没有则可以同new()创建一个实例;否则,直接向客户返回一个实例。

      在这种经典模式下,没有考虑线程并发获取实例问题,即可能出现两个线程同时获取instance实例,且此时其为null时,就会出现两个线程分别创建了instance,违反了单例规则。因此,需对上面代码修改。

    版本五:

    public class Singleton
    {
           private static Singleton instance;
           private static object _lock=new object();

           private Singleton()
           {

           }

           public static Singleton GetInstance()
           {
                   if(instance==null)
                   {
                          lock(_lock)
                          {
                                 if(instance==null)
    {
                                         instance=new Singleton();
                                 }
                          }
                   }
                   return instance;
           }
    }

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

    版本六:饿汉模式

    public sealed class Singleton
    {
            private static readonly Singleton instance=new Singleton();

            private Singleton()
            {
            }

            public static Singleton GetInstance()
            {
                   return instance;
            }
    }

    版本七:延迟初始化

    /// <summary>
    /// Delaies initialization.
    /// </summary>
    public sealed class Singleton
    {
        private Singleton()
        {
        }

        /// <summary>
        /// Gets the instance.
        /// </summary>
        public static Singleton Instance { get { return Nested._instance; } }

        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }

            internal static readonly Singleton _instance = new Singleton();
        }
    }

    版本八:静态初始化

    public sealed class Singleton
    {
        private static readonly Singleton _instance = new Singleton();

        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Singleton()
        {
        }

        /// <summary>
        /// Prevents a default instance of the
        /// <see cref="Singleton"/> class from being created.
        /// </summary>
        private Singleton()
        {
        }

        /// <summary>
        /// Gets the instance.
        /// </summary>
        public static Singleton Instance
        {
            get
            {
                return _instance;
            }
        }
    }

  • 相关阅读:
    python 学习笔记7(类/对象的属性;特性,__getattr__)
    linux 误删文件恢复
    python 学习笔记6(数据库 sqlite)
    hive 函数 Cube
    边标志法填充多边形
    tolua#代码简要分析
    CocoaAsyncSocket + Protobuf 处理粘包和拆包问题
    【设计模式】适配器模式
    【设计模式】外观模式
    【操作系统】进程管理(二)
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/5647125.html
Copyright © 2011-2022 走看看