• 《Android源码设计模式》--单例模式


    No1:

    懒汉单例模式优缺点分析

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

    优点:单例只有在使用时才会被实例化,在一定程度上节约了资源

    缺点:第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都进行同步,造成不必要的同步开销。

    所以这种模式一般不建议使用

    No2:

    Double Check Lock(DCL)双重检查锁定方式

    public class Singleton{
        private static Singleton sInstance = null;
        private Singleton(){}
        
        public void doSomething(){
            System.out.println("do sth.");
        }
        
        public static Singleton getInstance(){
            if(mInstance == null){
                synchronized(Singleton.class){
                    if(mInstance == null){
                        sInstance = new Singleton();
                    }
                }
            }
            return sInstance;
        }
    }

    优点:,第一次执行getInstance时单例对象才会被实例化,资源利用率高。第一层对instance判空主要是为了避免不必要的同步,第二层判断则是为了在null的情况下创建实例

    缺点:第一次加载时反应稍慢,也由于java内存模型的原因偶尔会失败。再高并发环境下也有一定缺陷,虽然发生概率很小

    No3:

    静态内部类单例模式

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

    第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方式不仅能够确保线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化,所以推荐使用

    No4:

    枚举单例

    public enum SingletonEnum{
        INSTANCE;
        public void doSomething(){
            System.out.println("do sth.");
        }
    }

    优点:线程安全,即使反序列化也不会重新生成新的实例

    No5:

    如果想杜绝单例模式对象在被反序列化时重新生成对象,那么必须加入readResolve函数

    public final class Singleton implements Serializable{
        private static final long serialVersionUID = 0L;
        private static final Singleton INSTANCE = new Singleton();
        
        private Singleton(){}
        
        public static Singleton getInstance(){
            return INSTANCE;
        }
        
        private Object readResolve() throws ObjectStreamException{
            return INSTANCE;
        }
    }

    也就是在readResolve方法中将单例对象返回,而不是重新生成一个新的对象。而对于枚举,并不存在这个问题

    No6:

    1)可序列化类中的字段类型不是Java的内置类型,那么该字段类型也需要实现Serializable接口

    2)如果调整了可序列化类的内部结构,例如新增、去除某个字段,但没有修改serialVersionUID,会引发异常。最好的方案是将值设置为0L,只是那些新修改的字段会为0或者null。

    No7:

    使用容器实现单例模式

    public class SingletonManager{
        private static Map<String,Object> objMap = new HashMap<String,Object>();
        
        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);
        }
    }

    优点:可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。

    No8:

    LayoutInflater.from(Context)来获取LayoutInflater服务

    Context是抽象类,在Application、Activity、Service中都会存在一个Context对象,即Context的总个数为Activity个数+Service个数+1。

    一个Activity的入口是ActivityThread的main函数。

    创建Context对象的实现类是ContextImpl

    No9:

    从ContextImpl类的部分代码中可以看到,在虚拟机第一次加载该类时会注册各种ServiceFetcher,其中就包含了LayoutInflater Service。将这些服务以键值对的形式存储在一个HashMap中,用户使用时只需要根据key来获取到对应的ServiceFetcher,然后通过ServiceFetcher对象的getService函数来获取具体的服务对象。当第一次获取时,会调用ServiceFetcher的createService函数创建服务对象,然后将该对象缓存到一个列表中,下次再取值时直接从缓存中获取,避免重复创建对象,从而达到单例的效果。系统核心服务以单例形式存在,减少了资源消耗。

    No10:

    LayoutInflater是一个抽象类,PolicyManager实际上是一个代理类,实现了IPolicy接口

    真正LayoutInflater的实现类是PhoneLayoutInflater

    No11:

    Activity的setContentView方法实际上调用的是Window的setContentView,Window是一个抽象类,具体实现类是PhoneWindow

    No12:

    createView相对比较简单,如果有前缀,那么构造View的完整路径,并且将该类加载到虚拟机中,然后获取该类的构造函数并且缓存起来,再通过构造函数来创建该View的对象,最后将View对象返回,这就是解析单个View的过程。通过rInflate的解析之后,整棵视图树就构建完毕。

    No13:

    单例模式的缺点

    1)单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现

    2)单例对象如果持有Context,那么很容易引发内存泄露,此时需要注意传递给单例对象的Context最好是Application Context

    No14:

    Window的View层级图

  • 相关阅读:
    css--一些基本属性
    python网络编程--TCP连接的三次握手(三报文握手)与四次挥手
    python--基础数据类型 set集合
    图片
    python--变量,常量,用户交互
    前端基础--css基本语法,选择器
    Python----一些面试题
    HTML--基本标签
    集合类型
    字典类型
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/7753931.html
Copyright © 2020-2023  润新知