zoukankan      html  css  js  c++  java
  • Singleton (单例) — 【面向对象设计模式学习】

    Singleton (单例) — 【面向对象设计模式学习】

    By CityWalker 2010年3月16日

    Intent

    a)     Ensure a class has only one instance, and provide a global point of access to it.

    b)     Encapsulated “just-in-time initialization” or “initialization on first use”.

    Scene

    Application needs one, and only one, instance of an object. Additionally, lazy initialization and global access are necessary.

    Structure

    Scheme of Singleton 

    Implementations

    There are various different ways of implementing the singleton pattern in C#. I shall present them here in reverse order of elegance, starting with the most commonly seen, which is not thread-safe, and working up to a fully lazily-loaded, thread-safe, simple and highly performant version.

    a)   First Version - not thread-safe

    public sealed class Singleton
        {
            static Singleton instance = null;
    
            Singleton()
            { }
    
            public static Singleton Instance
            {
                get
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
    
                    return instance;
                }
            }
        }
    

    b)   Second Version - simple thread-safety

    public sealed class Singleton
        {
            static Singleton instance = null;
            static readonly object padlock = new object();
    
            Singleton()
            { }
    
            public static Singleton Instance
            {
                get
                {
                    lock (padlock)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
    
                    return instance;
                }
            }
        }
    

    c)   Third Version - Double-check locking

    public sealed class Singleton
        {
            static Singleton instance = null;
            static readonly object padlock = new object();
    
            Singleton()
            { }
    
            public static Singleton Instance
            {
                get 
                {
                    if (instance == null)
                    {
                        lock (padlock)
                        {
                            if (instance == null)
                            {
                                instance = new Singleton();
                            }
                        }
                    }
    
                    return instance;
                }
            }
        }
    

    d)   Fourth Version - not quite as lazy, but thread-safe without using locks

    public sealed class Singleton
        {
            static readonly Singleton instance = new Singleton();
    
            static Singleton()
            { }
    
            Singleton()
            { }
    
            public static Singleton Instance
            {
                get
                {
                    return instance;
                }
            }
        }
    

    Note: It doesn't work in java.

    e)     Fifth Version - fully lazy instantiation

    public sealed class Singleton
        {
            public Singleton()
            { }
    
            public static Singleton Instance
            {
                get
                {
                    return Nest.instance;
                }             
            }
        }
    
        public class Nest
        {
            static Nest()
            { }
    
            internal static readonly Singleton instance = new Singleton();
        }
    

    Conclusion: 

        Singleton模式相对比较简单,有前辈们的总结,它的用法也就基本掌握了,就以上5种实现而言,第四种或第五种应该是比较适用的,无论从线程安全、性能、还是代码优雅方面都是不错的选择。对于.NET开发,第四种应该是首选,因为它很好的利用了.NET 平台的优势:“共语言运行库来初始化变量,解决了 Singleton 模式试图解决的两个基本问题:全局访问和实例化控制。公共静态属性为访问实例提供了一个全局访问点。此外,由于构造函数是私有的,因此不能在类本身以外实例化 Singleton 类;因此,变量引用的是可以在系统中存在的唯一的实例。”

          最后,对于吕老师的 C#设计模式(7)-Singleton Pattern 中提到的“不要使用单例模式存取全局变量。这违背了单例模式的用意,最好放到对应类的静态成员中。”不太理解,为什么会违背单例的用意呢 ?记得曾经遇到个问题,正是用单例才很好地解决了那个问题。看到吕老师这篇文章的时候,我有点迷惑了,下面是曾经的问题描述:

          向导式的数据导入工具,由4个窗体组成,各个窗体类中都会对一些公共的数据进行操作,由于公共的数据较多,而windows窗体间传递数据本来就不方便,于是想了个办法,利用Singleton模式构造一个辅助类,只允许实例化一个对象,用于存储这些公共数据。

     
        /// <summary>
        /// 助手类:用于各个页面间的数据传递
         /// </summary>
        public class ImportHelper
        {
            // 采用单例模式创建一个全局对象在各个页面间传递数据
            private static ImportHelper helper;
            private static object lockobject = new object();
            private ImportHelper() { }
    
            public static ImportHelper CreateHelper() 
            {
                if (helper == null)
                {
                    lock (lockobject)
                    {
                        if (helper == null)
                        {
                            helper = new ImportHelper();
                        }
                    }
                }
                return helper;
            }
    
            public static void DestroyHelper()
            {
                helper = null;
            }
    
    
            #region 属性字段
    
            private Dictionary<string, List<string>> _columns = new Dictionary<string, List<string>>();
            private Dictionary<string, System.Data.DataTable> _excelData = new Dictionary<string, DataTable>();
            private Dictionary<string, string> _tableMapping = new Dictionary<string, string>();
            private Dictionary<string, Dictionary<string, string>> _columnsMapping = new Dictionary<string, Dictionary<string, string>>();
            private Dictionary<string, string[]> _relationColumns = new Dictionary<string, string[]>();
            private Dictionary<string, string> _idsDic = new Dictionary<string, string>();
            private Dictionary<string, System.Data.DataTable> _tableData = new Dictionary<string, DataTable>();        
            private Dictionary<string, Dictionary<string, string>> _codeInfoValue = new Dictionary<string, Dictionary<string, string>>();        
            private Dictionary<string, System.Data.DataTable> _importData = new Dictionary<string, System.Data.DataTable>();
            private Dictionary<string, System.Data.DataTable> _failedData = new Dictionary<string, System.Data.DataTable>();
            private DataTable _errorDataTable = new DataTable();        
            private DataTable _wrongData = new DataTable();
            private DataTable _sourceTable = new DataTable();
            private DataTable _mappingTable = new DataTable();
            private List<string> _rootEntity = new List<string>();        
            private List<string> _unUseColumns = new List<string>();
            private string _excelPath = string.Empty;
            private string _mainSheet = string.Empty;
            private string _detailSheet = string.Empty;        
            private string _mainEntity = string.Empty;
            private int _mainCount = 0;
            private int _detailCount = 0;
            private int _mainFailedCount = 0;
            private int _detailFailedCount = 0;
            private ImportType _importKind;
                    
    
    
            //表列名集合:<文件名(不包含路径),文件中读取的列名集合>
            public Dictionary<string, List<string>> Columns
            {
                get { return _columns; }
                set { _columns = value; }
            }
            ......
    

    这里便是利用Singleton模式“存取全局变量”,并很好地解决了windows窗体间大量数据传递的问题,好像也没有什么问题哦。

  • 相关阅读:
    挑战程序设计竞赛 2.1 最基础的“穷竭搜索”
    HDU 5145 NPY and girls(莫队算法+乘法逆元)
    BZOJ 4300 绝世好题(位运算)
    HDU 5724 Chess(博弈论)
    BZOJ 1177 [Apio2009]Oil(递推)
    Codeforces 706D Vasiliy's Multiset(可持久化字典树)
    HDU 3374 String Problem (KMP+最小最大表示)
    POJ 2758 Checking the Text(Hash+二分答案)
    HDU 5782 Cycle(KMP+Hash)
    POJ 3450 Corporate Identity(KMP)
  • 原文地址:https://www.cnblogs.com/Reborn/p/1687266.html
Copyright © 2011-2022 走看看