定义 :确保某个类在系统中只有一个对象。
场景:访问IO和数据库资源等,要考虑单例。一个应用只有一个Application对象
关键点
- 构造函数不对外开放,一般为Private;
- 通过一个静态方法或枚举返回单例类对象;
- 确保单例类对象有且只有一个,尤其是在多线程环境下;
- 确保单例类对象在反序列化时不会重新构建对象;
第一种方式(饿汉),在一开始就以静态的方式建立好一个单例对象
public class Sington {
private static Sington sington=new Sington();
private Sington(){
}
public static Sington getSington(){
return sington;
}
}
第二种方式(懒汉),声明一个静态对象,只在第一次使用的时候进行初始化。
public class Sington {
private static Sington sington;
private Sington(){
}
public static synchronized Sington getSington(){
if (sington==null){
return sington=new Sington();
}
return sington;
}
}
优点:在使用时才进行初始化,使用之前不占资源
缺点:首次使用时,反应稍慢,每次调用都要同步,造成同步开销
第三种方式(DCL),在使用时才进行初始化,只有首次初始化期间,才会有同步开销
public class Sington {
private static Sington sington = null;
private Sington() {
}
public static Sington getSington() {
if (sington == null) {//避免不必要的同步
synchronized (Sington.class) {
if (sington == null) {//防止解锁时,已有实例化对象
return sington=new Sington();
}
}
}
return sington;
}
}
第四种方式(静态内部类单例模式),推荐
class Sington {
public static Sington getInstance() {
return SingtonHolder.sington;
}
private Sington() {
}
private static class SingtonHolder{
private static final Sington sington=new Sington();
}
}
第五种方式(枚举),超简单,反序列化还不会出错
public enum Sington {
INSTENCE
}
缺点 :
- 单例模式一般没有接口,扩展很困难,若要扩展,只能修改代码
- 单例对象如果持有Context,容易引发内存泄漏,传递给单例对象的Context最好是ApplicationContext