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);
}
}