单例模式——保证在整个应用程序的生命周期中,任何时刻单例类的实例都只存在一个(也可以不存在)。单例模式确保某一个类只有一个实例,而且自行实例化。单例模式的设计类如下
Singleton |
-static uniqueInstance -other Attribute |
+static getInstance()() +otherMethods() |
其中,类变量uniqueInstance持有唯一的单例实例,类方法getInstance()用来获取唯一的实例化对象。
全局变量和单例模式的区别:
1、全局变量是对一个对象的静态引用,虽然单例模式全局访问的功能全局变量也可以做到,但是全局变量不能保证应用程序中只有一个实例
2、编码规范明确指出少用全局变量,过多全局变量使得程序的可读性变差
3、全局变量不能实现继承。
单例模式在类中保存了它的唯一实例,可以保证只能创建一个实例,同时还提供了一个访问该唯一实例的全局访问点。使用单例模式需要注意:单例模式用来保证系统中一个类只有一个实例,单例类必须自己创建自己的唯一实例,单例类的构造函数必须为私有,单例类必须提供一个全局访问点。
public class Test{
private Test(){}
private static Test uniqueInstance = new Test();
public static Test getInstance(){
return uniqueInstance;
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*懒汉式——lazy loading
*第一次调用才初始化,避免浪费内存
*必须加锁才能保证单例,但加锁影响效率
*getInstance()的性能对应用程序不是很关键(该方法使用不太频繁)
*/
public class SingletonOfLazyLoading{
private static Log logger = LogFactory.getLog(SingletonOfLazyLoading.class);
private static SingletonOfLazyLoading instance;
private SingletonOfLazyLoading(){
logger.info("Singleton is constructing");
}
public static synchronized SingletonOfLazyLoading getInstance(){
if(instance == null){
instance = new SingletonOfLazyLoading();
}
return instance;
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 饿汉式
* 类加载时就初始化,浪费内存
* 没有用synchronize关键字
* @author mosq
*
*/
public class SingletonHungry {
private static Log logger = LogFactory.getLog(SingletonHungry.class);
private static SingletonHungry instance = new SingletonHungry();
private SingletonHungry() {
logger.info("SingletonHungry is constructing");
}
public static SingletonHungry getInstance() {
return instance;
}
}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新的值,
* 即jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的
* 采用双索机制,安全且在多线程情况下保持高性能
* @author mosq
*
*/
public class SingletonDCL {
private Log logger = LogFactory.getLog(SingletonDCL.class);
private volatile static SingletonDCL instance;
private SingletonDCL() {
logger.info("SingletonDCL is constructing");
}
public static SingletonDCL getInstance() {
if(instance == null) {
synchronized (SingletonDCL.class) {
if(instance == null) {
instance = new SingletonDCL();
}
}
}
return instance;
}
}