Head First 设计模式 第5章 单例模式

时间:2022-01-07 21:56:33

第5章 单例模式

1、定义:确保一个类只有一个实例,并为其创建访问点。

2、单例模式的类图:

Head First 设计模式 第5章 单例模式

  对应的单例模式的代码:

 package com.ek.singleton;
/**
* @包名 com.ek.singleton
* @文件名 Singleton.java
* @作者 edi_kai
* @创建日期 2015年8月25日
* @版本 V 1.0
* @描述
*/
public class Singleton { public static Singleton uniqueSingleton; private Singleton() {
} public static Singleton getInstance() {
if (null == uniqueSingleton) { //确保返回的是同一个对象
uniqueSingleton = new Singleton();
}
return uniqueSingleton;
}
}

  这样的单例模式真的没问题吗?当然有。当有两个线程同时调用getInstance方法时,就有可能返回两个Singleton对象。

  那么,我们该如何解决这个问题呢?将方法getInstance设置成线程同步的,如下:

 package com.ek.singleton;
/**
* @包名 com.ek.singleton
* @文件名 Singleton.java
* @作者 edi_kai
* @创建日期 2015年8月25日
* @版本 V 1.0
* @描述
*/
public class Singleton { public static Singleton uniqueSingleton; private Singleton() {
} public static synchronized Singleton getInstance() {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
return uniqueSingleton;
}
}

  这是我们设置成线程同步之后的代码,这样可以避免上面说的问题,但是又引入了新的问题:同步一个方法会使效率降低100倍,如果getInstance方法使用比较频繁,我们得需要考虑其他方法来解决问题。

  看下面的代码:

 package com.ek.singleton;
/**
* @包名 com.ek.singleton
* @文件名 Singleton.java
* @作者 edi_kai
* @创建日期 2015年8月25日
* @版本 V 1.0
* @描述
*/
public class Singleton { public static Singleton uniqueSingleton = new Singleton(); private Singleton() {
} public static Singleton getInstance() {
return uniqueSingleton;
}
}

  这里我们直接在静态初始化器中实例化对象,这样JVM在加载这个类的时候,会马上创建这个对象,保证了唯一性。存在的问题是:只要JVM加载该类,对象就会被实例化,不管现在我们是不是需要这个实例化对象。

  那么让我们来看最后一种方法,如下:

 package com.ek.singleton;
/**
* @包名 com.ek.singleton
* @文件名 Singleton.java
* @作者 edi_kai
* @创建日期 2015年8月25日
* @版本 V 1.0
* @描述
*/
public class Singleton { public volatile static Singleton uniqueSingleton; private Singleton() {
} public static Singleton getInstance() {
if (null == uniqueSingleton) {
synchronized (Singleton.class) {//只有在第一次实例化对象的时候会同步,即便调用比较频繁,也不会影响性能
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
}

  这种方式其实就是最理想的方式,其中volatile关键字确保当uniqueSingleton变量被初始化成Singleton实例时,多个线程可以正确的处理uniqueSingleton变量。该方式也有一个问题,那就是volatile关键字需要JDK 1.4以上才支持,在1.4及以下版本中被忽略了,(/ □ \)。

  好了,到这里单例模式我们就介绍完了,一定要根据自己的实际环境来确定使用哪一种方式的来实现单例模式哦....

谢谢阅读

转载请注明出处,谢谢!