博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
单例模式在Java和C#中的实现
阅读量:5335 次
发布时间:2019-06-15

本文共 3487 字,大约阅读时间需要 11 分钟。

   单例模式算是最常见和最容易理解一种设计模式了。通常是指某一个类只有一实例存在,存在的空间我认为可以理解为该类所在的应用系统内,还有一种是在某一个容器内单一存在,比如像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
() { 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; } }

 

思路很简单,一个键值对容器存放类的实例,使用类全名作为唯一键,要创建类实例时先从容器查找如果有则返回该对象,如果没有则新实例化一个并放入容器。

转载于:https://www.cnblogs.com/james1207/p/3423922.html

你可能感兴趣的文章
luoguP3414 SAC#1 - 组合数
查看>>
五一 DAY 4
查看>>
关于System.__ComObject一些问题
查看>>
java stringbuffer二
查看>>
[hihoCoder] 拓扑排序·一
查看>>
(转)接口测试用例设计(详细干货)
查看>>
js Math对象方法 (个人学习笔记)
查看>>
helm-chart-2-chart结构和简单模板
查看>>
转载Repository 和Unit of work的使用说明
查看>>
【译】SSH隧道:本地和远程端口转发
查看>>
win8.1安装Python提示缺失api-ms-win-crt-runtime-l1-1-0.dll问题
查看>>
图片点击轮播(三)-----2017-04-05
查看>>
判断两个字符串是否相等【JAVA】
查看>>
直播技术细节3
查看>>
《分布式服务架构:原理、设计于实战》总结
查看>>
java中new一个对象和对象=null有什么区别
查看>>
字母和数字键的键码值(keyCode)
查看>>
协议和代理
查看>>
IE8调用window.open导出EXCEL文件题目
查看>>
sql server 2008 不允许保存更改,您所做的更改要求删除并重新创建以下表 的解决办法(转)...
查看>>