单例模式在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;
}
}
思路很简单,一个键值对容器存放类的实例,使用类全名作为唯一键,要创建类实例时先从容器查找如果有则返回该对象,如果没有则新实例化一个并放入容器。
单例模式在Java和C#中的实现的更多相关文章
- 编写Java程序,中国道教中掌管天宫的最高权力统治者是玉帝(Emperor),我们可以认为玉帝是一个单例模式,在这个场景中,有玉帝和天宫的大臣(Minister)们,大臣每天要上朝参见玉帝,而每一天参
查看本章节 查看作业目录 需求说明: 中国道教中掌管天宫的最高权力统治者是玉帝(Emperor),我们可以认为玉帝是一个单例模式,在这个场景中,有玉帝和天宫的大臣(Minister)们,大臣每天要上朝 ...
- 你真的会写单例模式吗-------Java实现
转载: 你真的会写单例模式吗--Java实现 单例模式可能是代码最少的模式了,但是少不一定意味着简单,想要用好.用对单例模式,还真得费一番脑筋.本文对Java中常见的单例模式写法做了一个总结,如有错漏 ...
- [转] 你真的会写单例模式吗——Java实现
你真的会写单例模式吗——Java实现 原文:http://www.tuicool.com/articles/MBrUfy6 单例模式可能是代码最少的模式了,但是少不一定意味着简单,想要用好.用对单例模 ...
- Java并发编程中的设计模式解析(二)一个单例的七种写法
Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ...
- 浅谈单例模式及其java实现
单例模式是23种设计模式中比较简单的一种,在此聊一下单例模式. 1.什么是设计模式? 对于没有接触过设计模式的人来说,一听到设计模式这四个字就觉得这个东西很高深莫测,一下子就对这个东西产生了恐惧感,其 ...
- JAVA WEB项目中各种路径的获取
JAVA WEB项目中各种路径的获取 标签: java webpath文件路径 2014-02-14 15:04 1746人阅读 评论(0) 收藏 举报 分类: JAVA开发(41) 1.可以在s ...
- 揭开Java IO流中的flush()的神秘面纱
大家在使用Java IO流中OutputStream.PrintWriter --时,会经常用到它的flush()方法. 与在网络硬件中缓存一样,流还可以在软件中得到缓存,即直接在Java代码中缓存. ...
- JAVA安装过程中出现的“javac不是内部或外部指令”的解决方法
近来重新安装了JAVA,安装过程中出现问题,网上找到解决办法,汇总发布. 解决流程: 1.确定自己的环境变量设置没问题,没有出现遗漏 : . 等情况 (具体环境变量设置百度) 2.环境变量设置后 ,d ...
- Java Web开发中MVC设计模式简介
一.有关Java Web与MVC设计模式 学习过基本Java Web开发的人都已经了解了如何编写基本的Servlet,如何编写jsp及如何更新浏览器中显示的内容.但是我们之前自己编写的应用一般存在无条 ...
随机推荐
- 用css实现云状提示框
经常会用到云状提示框,如图: 基本框架是这样,以三角在左侧为例: <div class="container"> <div class="content ...
- [转]ANDROID L——Material Design详解(动画篇)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 转自:http://blog.csdn.net/a396901990/article/de ...
- Java获取本地IP地址
import java.net.InetAddress; import java.net.UnknownHostException; public class IpTest { public stat ...
- Using dbms_shared_pool.purge to remove a single task from the library cache
我们都知道可是使用 alter system flush shared_pool 来清除shared pool 信息,当时不能指定清除某个对象.因为在系统繁忙的时侯 使用 alter system f ...
- Nested transactions in stored procedure of SQLServer
question: if the nested transaction encountered an exception, then rollbacked. How about the outer t ...
- 什么是BI及哪些行业需要用到BI?
什么是BI?哪些行业需要用到BI?BI——就是分析利用企业已有的各种商用数据来了解企业的经营状况和外部环境,从而为企业的经营决策提供数据支撑.下面我们来详细分解下: 企业应用BI的目标即是期望通过对来 ...
- ref 关键字修饰引用类型
对于再分配引用对象的引用的操作,没有Ref修饰时是不能在外部生效的,只有有Ref修饰的引用参数才能使再分配操作应用于外部 侵删.
- Java 杨辉三角的简单实现
package com.lf.trianglenumber; public class Test { public static void main(String[] args) { // 打印的行数 ...
- mysql -prompt选项
使用-pormpt修改提示符.可以在登录时或者在登录后使用prompt选项来修改提示符 (1)使用mysql命令行参数修改提示符 # mysql -u root -p Enter password: ...
- C++Primer 第十三章
//1.当定义一个类时,我们显示地或隐式地指出在此类型的对象(注意这里是此类型的对象,而不包括此类型的指针)拷贝,移动,赋值,销毁时做什么.一个类通过定义五种特殊的成员函数来控制这些操作:拷贝构造函数 ...