美文网首页Android技术知识Android开发Android知识
每日Android源码设计模式之-一、单例模式

每日Android源码设计模式之-一、单例模式

作者: Alexey | 来源:发表于2017-03-09 08:52 被阅读0次

    单例设计模式是应用最广的,它必须保证一个实例,例如一个ImageLoader实例,自行实例化并且向整个系统提供这个实例。

    当创建一个对象的时候消耗过多,例如要访问IO、数据库资源等时使用。


    特点

    1.构造函数不对外开放,private。

    2.通过一个静态方法或者枚举返回单例类对象。

    3.确保单例对象只有一个,特别是多线程。

    4.确保在反序列化时不会重新构建对象


    分为两种:

    饿汉:类一创建就new对象出来。

    懒汉:使用时候才去通过判断对象是否为null来new新对象。


    为了保证对象唯一,有几种实现方法:

    1.懒汉DCL(DoubleCheckLock)(一般能满足需求)

    双重校验同步代码块方法去new对象。

    缺点:

    高并发下,由于不是原子操作,可能会失效,

    java5以后,可以在成员变量上加上volatile来禁止该对象上的读写指令重排序。

    2.静态内部类单例模式: 推荐

    3.枚举单例 避免发序列化产生对象另类:容器实现单例模式

    缺点:

    接口扩展困难,

    如果传入的是Activity的context 很可能内存泄露

    4.使用容器来实现单例。


    android源码中的单例模式:

     我们常常通过context来获取系统级别的服务,如WindowsManagerService、ActivityManagerService等,跟常用的是LayoutInflater类。

    下面来分析下LayoutInflater

    LayoutInflater.form(context)获取单例->点进去也是调用了context.getSystemService(context.LAYOUT_INFLATER_SERVICE)

    我们知道Activity对象和Context对象是在ActivityThread的main函数中生成的,找到main函数发现context是ComtextImpl.createActivityContext(this,r.pakageInfo,t.token)生成,然后通过activity.Attach传入Activity中的。

    最后来看ComtextImpl类

    这里使用的使用容器实现单例模式。

    容器:private static final HashMap<String,ServiceFetcher> SYSTEM_SERVICE_MAP = new ...;

    //在ComtextImpl类static代码块中,会生成各种ServiceFatcher,然后存入SYSTEM_SERVICE_MAP中。

    ComtextImpl类有一个getSystemService(String name)方法用来获取存入SYSTEM_SERVICE_MAP中的ServiceFatcher对象,然后调用fetcher.getServiece(comtextImpl)方法。

    fetcher中的getServiece方法从缓存ctxImpl.mServiceCache中获取对象cache.get(mContextCacheIndex)避免重复创建。



    我们如何运用单例模式

    例子:

    ImageLoader使用DCL(Double checkLock)的方式来获取对象

    public static InmageLoadegetInstance(){

     if(sInstance ==null){

        synchronized(ImageLoader.class){

          i f(sInstance ==null){

            sInstance = new ImageLoader();

          }

        }

      }

    }

    相关文章

      网友评论

        本文标题:每日Android源码设计模式之-一、单例模式

        本文链接:https://www.haomeiwen.com/subject/hhtngttx.html