Android设计模式学习笔记(单例模式)
注:该学习笔记来源于《Android 源码设计模式解析与实战》一书,请喜欢的读者购买正版书籍,若觉得本文侵权请博客上留言,马上处理
5种实现方式
1、懒汉模式
2、Double Check Lock(DCL)模式
3、静态内部类单例模式
4、枚举单例模式
5、容器单例模式
懒汉设计模式
- 实用性:一般不用;
- 优点:在第一次使用时才进行初始化;
- 缺点:
- 第一次使用时需要先实例化,反应稍慢;
- 每次使用时都要进行同步(synchronized为方法上的锁),每一次获取都需要去同步,造成不必要的开销;
DCL单例模式
- 实用性:经常使用
- 优点:资源利用率高,第一次执行getInstance时单例对象才被实例化,效率高
- 缺点:
- 第一次加载反应稍慢
- 在高并发情况下因为java内存模型的原因偶尔失败。发生概率小
public class singleton{
private volatile static Singleton instance=null;
private Sington(){
}
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(mInstance==null){
instatce=new Instance();
}
}
}
return instance;
}
}
加入volatile 为保证其原子性操作,因为在instatce=new Instance();这句语句中,会被编译成多条汇编指令,分别为分配内存空间,初始化构造函数和初始化成员字段,给instance指向分配的内存空间,而后两步的执行顺序不固定的。
静态内部类单例模式
- 实用性:推荐使用,因为DCL在某些情况下会失效,所以在《Java 并发编程实践》中推荐使用下面代码代替
- 优点:线程安全,唯一性,延迟加载
- 缺点:
- 第一次加载反应稍慢
public class singleton{
private Sington(){
}
private Sington(){
return SingletonInter.instance;
}
private static class SingletonInter{
private static final Singleton instance=new instance();
}
}
- 在初始化Singleton的时候并不会初始化instance,只有在第一次调用的时候才会导致虚拟机加载SingletonInter类
枚举单例模式
- 实用性:一般
- 优点:线程安全,在任何情况下都是一个单例
public enum singletonEnum{
INSTATCE;
}
在其他单例中,若进行序列化然后反序列化,会重新进行创建对象,若要杜绝这种情况,必须重写钩子函数readResolve(),而枚举不存在这种情况
private Object readResolve() throws ObjectStreamException{
return instance;
}
容器单例模式
public class singleton{
private static Map<String,Object> objMap=new HashMap<String,Object>();
private Sington(){
}
public static void registerSingleton(String key,Object instance){
if(!objMap.containsKey(key)){
objMap.put(key,instance);
}
}
public static Object getSingleton(String key){
return objMap.get(key);
}
}