您的位置:首页 > 编程语言 > Java开发

设计模式之单例模式java语言的实现

2017-04-25 10:56 274 查看
首先看一下单例模式的定义

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例,所有的都共享这个实例。既然规定一个类只有一个实例,也即使如何保证一个对象实例化的唯一性,那么该如何实现呢?

单例模式下存在两种实现模式

1.懒汉模式

顾名思义,通过名称我们可以理解,既然谈到了懒汉,就是到真正用的时候才初始化,若是不用,那么就一直懒在那里。

2.饥汉模式

所谓饥汉模式,就是在类装载的时候就给初始化了,满足其饥饿的的需求

下面看看JAVA语言下单例的实现

版本一:java语言下最简单的懒汉模式

/**
*懒汉加载模式,全局的单例实例在第一次初始化的时候被加载
*/
public class Single1 {
private static Single1 instance=null;
//构造方法改成私有
private Single1(){

}

public static Single1 getInstance(){
if (instance==null) {
instance=new Single1();
}
return instance;
}
}

版本一是最简单的懒汉模式实现的代码,代码简单易懂,那么这种代码存在什么样的弊端的?多线程下如何是否能保证获取的实例是唯一的?那么我们来看下版本三,是该版的增强版,加入了synchronized,实现方法的“独占性”。

版本二:java语言下最简单的饥汉模式

/**
* 饥汉模式 在类装载的时候构建
*/
public class Single2 {
private static Single2 instance=new Single2();

private Single2(){

}

private static Single2 getInstance(){
return instance;
}
}

版本二是最简单的饥汉模式下java代码的实现,这里不做多说,在下面的几个版本对比过后再详细阐述说明。

版本三:针对版本一的增强版(同步方法版)

/**
* 懒汉模式下的改进  Syn版
*/
public class Single3 {
private static Single3 instance=null;

private Single3(){

}

public static synchronized Single3 getInstance(){
if (instance==null) {
instance=new Single3();
}
return instance;
}

}

版本三是版本一的增强版,使用同步方法实现,当多线程的环境下进入此方法,只能保证一个线程进入此方法,而别的线程就无奈的等着,直到线程释放后后面的线程才有机会占有该方法。版本三解决了版本一在多线程环境下无法获取唯一实例的问题。

问题来了,这个版本有没有什么问题呢?是不是就算是perfect的呢?答案是否定的,我们知道用synchronized修饰方法的时候,那么此方法在多线程的环境下有且仅有一个可以进入此方法,那么问题就来了,这样情况下吞吐率是不是就很低了?是的,没错,那么在版本三的基础上是否还有更好的方案呢?

版本四:针对版本三的增强版

/**
* 懒汉模式 syn改进版
*/
public class Single4 {
private static Single4 instance=null;

private Single4(){

}

public static Single4 getInstance(){
if (instance==null) {
synchronized (Single4.class) {
if (instance==null) {
instance=new Single4();
}
}
}
return instance;
}

}首先对比一下版本三和版本四,是不是发现变化不是很大,只是稍作改动,而正是这样的稍作改动,多线程的环境下就提升了很大的效率。简单解释一下,首先方法不是独占的,当判断第一次instance==null的时候,这里多线程都是可以跑到此处的,ok,synchronized就来了,此处霸道的独占就开始了。下面还有一个instance==null的判断,为什么呢?我个人理解,多线程情况下,可能在第一个null的判断之处有的已经执行了,那么此处做一次判断,避免了多实例的情况。

版本五:针对版本四的增强版

/**
*
* 懒汉模式  共享对象,Syn版
*/
public class Single5 {
private static volatile Single5 instance=null;

private Single5(){

}

public static Single5 getInstance(){
if (instance==null) {
synchronized(Single5.class){
if (instance==null) {
instance=new Single5();
}
}
}
return instance;
}
}

该版本是在版本四的基础上再次做了一次改进。该版本引入了voliatile关键字,实现了多线程环境下线程内存的数据共享。个人认为版本四基本可以满足日常开发的需求;

至此,五个版本已经写完,下面简要说下懒汉模式和饥汉模式个人的一些看法:

1.加载时间不同,饥汉模式是在JVM启动,类加载的时候加载。懒汉模式是在第一次实例化的时候加载。

2.可使用,可扩展性不同,比如,单例变量需要使用一些变量或者参数等,那么饥汉模式的弊端就彰显出来了。

Ok,花费了两个小时的时间,代码实现和文章的书写基本结束,可能存在部分不足之处,后期会补上或者大家提建议,谢谢


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 单例模式