单例模式(Singleton Pattern):
在平时的开发中,可能会用到单例模式,许多java的笔试题中也会叫笔试者写出单例模式的那几种写法并且分析。那么下面就来轻轻地探讨一下,最简单的设计模式,即单例模式。
单例模式的解释:
GoF对单例模式的定义:保证一个类只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。说的意思就是一个类在整个程序中就只能有一个实例,并且这个类中要定义一些可以全局访问的属性、方法等。
单例模式的要点有三:
1、有且仅有一个实例。 2、自己创建自己的实例。 3、自己向整个应用程序提供这个实例。
单例模式的应用场景:
如窗口管理系统、打印缓冲池、文件系统它们都是原型的例子。
单例模式按实例化对象的时间先后可以大体分为两种类型,即饿汉式和懒汉式,接下来将列出5种单例模式的写法,并分析他们缺点。
第一种:饿汉式
第二种:懒汉式(一)
第三种:懒汉式(二)- 方法同步
第四种:懒汉式(三)- 双重检查
/**
* 单例模式-懒汉式(三)
*/
public class Singleton {
private static Singleton instance ;
// 够造函数必须是私有的,不能被外部直接调用。
private Singleton(){
}
// 暴露给外部,提供实例。
public static Singleton getInstance(){
// 1
if(instance == null){
// 2
synchronized(Singleton.class){
// 3
if(instance == null){
// 4
instance = new Singleton();
// 5
}
}
}
return instance ;
}
}
/**
* 单例模式-懒汉式(三)
*/
public class Singleton {
private static Singleton instance ;
// 够造函数必须是私有的,不能被外部直接调用。
private Singleton(){
}
// 暴露给外部,提供实例。
public static Singleton getInstance(){
// 1
if(instance == null){
// 2
synchronized(Singleton.class){
// 3
if(instance == null){
// 4
instance = new Singleton();
// 5
}
}
}
return instance ;
}
}
第一个if判断存在的必要性在于提高性能,只有第一次调用getInstance()方法是才会被调用。
第二个if判断存在的必要性在于实现单例,当很多线程在同步块外面等待一个个进入时,如果发现instance不为空了,则不实例化。
缺点:在多线程环境中任然不安全。
例如:多线程的涉入可能会导致instance还没有初始化完成就被当做完整的实例返回给了应用程序了。也就是说线程1正在实例化instance,
线程2运行到//1这个位置发现instance不为空,那么按程序的流程就应该返回instance,但是这个时候的instance还未被实例化完成。
第五种:懒汉式(四)- 内部类
/**
* 单例模式-懒汉式(四)
*/
public class Singleton {
// 够造函数必须是私有的,不能被外部直接调用。
private Singleton(){
}
// 暴露给外部,提供实例。
public static Singleton getInstance(){
return SingletonHolder.instance;
}
// 静态内部内,实现延时加载
private static class SingletonHolder{
public static Singleton instance = new Singleton();
}
}
/**
* 单例模式-懒汉式(四)
*/
public class Singleton {
// 够造函数必须是私有的,不能被外部直接调用。
private Singleton(){
}
// 暴露给外部,提供实例。
public static Singleton getInstance(){
return SingletonHolder.instance;
}
// 静态内部内,实现延时加载
private static class SingletonHolder{
public static Singleton instance = new Singleton();
}
}
经过这5种写法各有千秋,都有好有坏,现在大家用双重检查用得比较多,当然我觉得还是懒汉式(四)要好一点,这个跟android里面绑定service很相似,但是仅仅是内部类这一点。