设计模式汇总(Android角度)

设计模式

单例模式

  • 定义就是单例对象的类必须保证只有一个实例存在
  • 适用于创建一个对象需要消耗过多资源的情况,例如访问数据库等资源
  • 构造函数私有化(才不会让你有机会再创建一个对象)
  • 静态方法或枚举返回单例对象
  • 保证在多线程环境下对象也是单例的
  • 单例类对象在反序列化是不会重新构建对象的

饿汉式

public class Singleton {
    private final static Singleton instance = new Singleton();
    //私有化构造器
    private Singleton(){}
    
    //共有静态方法,对外暴露获取单例对象
    public static Singleton getInstance(){
        return instance;
    }
}

在静态对象声明时就已经初始化 getInstance -> instance

懒汉式

public class Singleton {
    private static Singleton instance = null;

    private Singleton(){}

    public static synchronized Singleton getInstance(){
        if(null == instance){
            instance = new Singleton();
        }
        return instance;
    }
}

不同于前者,静态对象声明的时机不同,通过保证getInstance方法是同步的来保证多线程中该变量也是单例。另一方面,getInstance每次同步导致了更多资源消耗。

getInstance -> synchronized判断 ->有则返回Instance,无则创建

Double Check Lock(DCL)

前者的改进,既能在需要时才初始化对象,又能保证线程安全,而且在对象初始化之后调用getInstance()不进行同步

public class Singleton {
    private volatile static Singleton instance = null;

    private Singleton(){}

    public static Singleton getInstance(){
        if(null == instance){
            synchronized(Singleton.class){
                if(null == instance){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

getInstance -> 判空 -> synchronized ->判空 -> new

由于语句new Singleton不是原子性操作 有可能先执行了对象初始化操作,再回到原线程执行构造函数,出错。就要使用volatile保证原子性。

静态内部类

public class Singleton {
    private Singleton(){}
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
    
    /**静态内部类*/
    private static class SingletonHolder{
        public static final Singleton instance = new Singleton();
    }
}

该种方式可以保证多线程并发的时候不会发生问题

第一次调用getInsance ->加载SingletonHolder类 ->new

加载一个类时,其内部类不会同时被加载。一个类被加载,当且仅当其某个静态成员(静态域、构造器、静态方法等)被调用时发生。

枚举单例

public enmu SingletonEnum {
    INSTANCE;
}

简单粗暴,用于保证反序列化也不会重新生成新的实例。

使用容器实现单例模式

public class SingletonManager{
    private static Map objMap = new HashMap<>();
    
    private SingletonManager(){}
    
    public static void registerService(String key,Object instance){
        if(!objMap.containsKey(key)){
            objMap.put(key,instance);
        }
    }
    
    public static Object getService(String key){
        return objMap.get(key);
    }
}

可以管理多种类型的单例,使用时用同意的接口操作,LayoutInflater就是用的这种模式。

registerService->Map.containKey判断->初始化put对象进去->getService

优点

  • 只存在一个实例,减少了内存开支,减少了系统的性能开销
  • 避免对资源的多重占用
  • 全局的访问点,优化和共享资源访问

缺点

  • 没有接口,难扩展,只能修改代码
  • 如果持有Context容易导致内存泄露(需要传递Context的话最好是Application Context)

你可能感兴趣的:(设计模式汇总(Android角度))