• 单例模式在Java和C#中的实现


       单例模式算是最常见和最容易理解一种设计模式了。通常是指某一个类只有一实例存在,存在的空间我认为可以理解为该类所在的应用系统内,还有一种是在某一个容器内单一存在,比如像spring的IOC容器(作用域为singleton的bean在容器内是单例存在的),也可以是个简单的HashMap。

    单例模式的实现通常分两种,按习惯叫法是饿汉式和懒汉式,这两种的区别主要在于是否延迟初始化。以下是java的饿汉式单例实现:

    public class SingletonDemo {
         //私有默认构造函数
          private SingletonDemo() {}
         //已经自行实例化 
         private static final SingletonDemo single = new SingletonDemo();
    
         public static SingletonDemo getInstance() {
             return single;
         }
     }


    C#的实现与这个基本无异,单例的两个实现步骤是一私有化默认构造函数,使得类不可以在外部通过new操作实例化 (注:可以利用反射实例化),

    二是内部自身实例化了一个对象供外部使用。那么取得一个SingletonDemo对象只能通过它的静态方法getInstance()了。我们再来看懒汉式的实现:

      public class SingletonDemo {
    
          private SingletonDemo() {}
          //注意这里没有final    
          private static SingletonDemo single=null;
    
          public synchronized static SingletonDemo getInstance() {
               if (single == null) {  
                 single = new SingletonDemo();
             }  
            return single;
         }
     }
    
    
    
    
    C#的实现:
    public class SingletonDemo
    {
           private static SingletonDemo instance;
           private static object _lock=new object();
    
           private SingletonDemo()
           { }
    
           public static SingletonDemo GetInstance()
           {
                   if(instance==null)
                   {
                          lock(_lock)
                          {
                                 if(instance==null)
                                 {
                                         instance=new SingletonDemo();
                                 }
                          }
                   }
                   return instance;
           }
    }

    懒汉式主要在于使用时再实例化,可以说二者区别不大。另外懒汉式的一个缺点是要处理多线程调用而产生多个实例的问题,java使用了synchronized同步方法,而C#使用的是lock互斥锁。从这点上来说本人更喜欢饿汉式的简洁。

       由上面我们已经知道了两种实现方式区别在于类成员的初始化顺序,我们看看java的成员初始化顺序:静态变量、静态初始化块)>(变量、初始化块)>构造器

    很显然我们还可以在静态初始块中为single赋值

    static final SingletonDemo single;

    static{

     single=new SingletonDemo();

    //还可以干点其他事,比如启动一个hibernate的SessionFactory,哈哈

    }

    再看C#的,C#中是没有静态块这一说的,代替它的是静态函数

    static readonly SingletonDemo single;

    static SingletonDemo()

    {

    single=new SingletonDemo();

    }

    这里要提下的是有些人喜欢在静态块中做一些赋值或操作,NHibernate(.net版的hibernate)的示例有这么一段:

    public class NHibernateHelper 
    {
    public static readonly Configuration _Configuration;
            private const string _CurrentSessionKey = "nhibernate.current_session";
            private static readonly ISessionFactory _SessionFactory;
    
            static NHibernateHelper()
            {
                log4net.Config.XmlConfigurator.Configure();
                _Configuration = new Configuration();
                 _SessionFactory = _Configuration.Configure().BuildSessionFactory();
              
            }
    }

    当hibernate配置文件中的数据库配置存在错误时,这里将出现异常,而由于静态函数只在类初始化时运行一次,所以这个异常是不能弥补的,我们只能重启应用再试一次了。


    我们也实现一个在容器内的单例,这回来个C#版的吧:

     public class DALFactory
        {
            private static Hashtable cacheDAL = new Hashtable();
    
            public static T createDAL<T>()
            {
                string CacheKey = typeof(T).FullName;//使用类全名作为key
                T dal = (T)cacheDAL[CacheKey];
                if (dal == null)
                {
                    lock (cacheDAL)
                    {
                        if (dal == null)
                        {
                            Type t = typeof(T);
                            dal = (T)Activator.CreateInstance(t);//反射实例化类
                            try
                            {
                                cacheDAL.Add(CacheKey, dal);
                            }
                            catch (ArgumentException) { }
                        }
                    }
                }
                return dal;
            }
        }
    思路很简单,一个键值对容器存放类的实例,使用类全名作为唯一键,要创建类实例时先从容器查找如果有则返回该对象,如果没有则新实例化一个并放入容器。
  • 相关阅读:
    自闭的D7
    D2
    Codeforces Round #531 (Div. 3)
    hello 2019 D
    牛客练习赛36B
    cf954H
    gym102007 E
    Gym 101972
    Gym 101810
    试题 历届试题 青蛙跳杯子(bfs)
  • 原文地址:https://www.cnblogs.com/james1207/p/3423922.html
Copyright © 2020-2023  润新知