单例模式介绍
单例模式是应用最广的模式之一,也可能是很多初级工程师唯一会使用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个全局对象,这样有利于我们协调系统整体的行为。如在一个应用中,应该只有一个ImageLoader实例,这个ImageLoader中又含有线程池、缓存系统、网络请求等,很消耗资源,因此,没有理由让它构造多个实例。这种不能自由构造对象的情况,就是单例模式的使用场景。
单例模式的定义
确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式的使用场景
确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某个类型的对象只应该有且只有一个。例如,创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源,这时就要考虑使用单例模式。
单例模式的几种实现方式:
- Double Check LOCK(DCL)双重检查锁定(不推荐)
DCL优点:资源利用率高,第一次执行getInstance时对象才会被实例化,效率高。缺点:第一次加载时反应慢,也由于java内存模型原因偶尔会失败。在高并发环境下也有一定缺陷,虽然发生概率很小。DCL模式是使用最多的单例实现方式,它能够在需要时实例化单例对象,并且在绝大多数情况下保证单例对象的唯一性,除非你的代码在并发场景比较复杂或者低于1.6版本下使用,否则,这种方式一般能满足需求
public class Singleton {
private static Singleton mInstance = null;
private Singleton(){}
public static Singleton getsInstance(){
if(mInstance==null){
synchronized (Singleton.class){
if(mInstance == null){
mInstance = new Singleton();
}
}
}
return mInstance;
}
}
- 静态内部类单例模式(推荐)
DCL 虽然在一定程度上解决了资源消耗、多余的同步、线程安全等问题,但是它还是在某些情况下出现失效的问题。这个问题被称为双重检查锁失效,在《java并发编程实践》一书中 最后谈到这个问题,并指出这种“优化”是丑陋的,不赞成使用。而建议使用如下代码代替:
public class Singleton {
private Singleton(){}
public static Singleton getsInstance(){
return SingleTonHolder.mInstance;
}
/**
* 静态内部类
*/
private static class SingleTonHolder{
private static final Singleton mInstance = new Singleton();
}
}
- 枚举单例
public class Configurator {
public static Configurator getInstance(){
return Holder.INSTANCE;
}
//静态内部类的单例初始化
private static class Holder{
private static final Configurator INSTANCE = new Configurator();
}
}
- 使用容器实现单例模式(略)
参考《Android 源码设计模式》