《Android源码设计模式解析与实战》读书笔记-单例模式

2017-03-06  本文已影响25人  appcompat_v7

介绍

单例对象的类必须保证只有一个实例存在。
某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

场景

避免产生多个对象消耗过多资源,或者某种类型的对象只应该有且只有一个。例如创建一个对象需要访问IO和数据库等资源,这时候就该考虑使用单例模式。

关键点

  1. 构造函数不对外开放,一般为private
  2. 通过一个静态方法或者枚举返回实例。
  3. 确保实例只有一个,尤其是在多线程的情况下。
  4. 确保单例对象在反序列化时不会重新构件对象。

简单示例

为了避免单例对象实例化以后进行不必要的同步,所以对实例对象进行第一次判空,如果此时实例对象已经被实例化,那么将不会执行同步代码块。当同步后依然为空,另外,用volatile关键字修饰实例对象,保证每一次都从主存中读取对象,避免多线程的情况下出现问题。

Android源码中的单例模式

LayoutInflater类,我们经常会在ListView中的getView方法使用到LayoutInflater,示例代码:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null){
        convertView = LayoutInflater.from(mContext).inflate(layoutiId,parent,false);
    }else {

    }

    return convertView;
}

通过LayoutInflater.from(context)来获取LayoutInflater的服务,下面是具体实现:

/**
 * Obtains the LayoutInflater from the given context.
 */
public static LayoutInflater from(Context context) {
    LayoutInflater LayoutInflater =
            (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (LayoutInflater == null) {
        throw new AssertionError("LayoutInflater not found.");
    }
    return LayoutInflater;
}

因为Context是一个Abstract类,getSystemService方法的具体实现在Context的实现类中,进入ContextImpl类定位到具体实现:

  public Object Object getService(ContextImpl ctx) {
    ArrayList<Object> cache = ctx.mServiceCache;
    Object service;
    synchronized (cache) {
    if (cache.size() == 0) {
    // Initialize the cache vector on first access.
    // At this point sNextPerContextServiceCacheIndex
    // is the number of potential services that are
    // cached per-Context.
    for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {
          cache.add(null);
        }
    } else {
    service = cache.get(mContextCacheIndex);
    if (service != null) {
        return service;
      }
    }
    service = createService(ctx);
    cache.set(mContextCacheIndex, service);
    return service;
  }
}

可以看到。ContextImpl中使用了一个HashMap存放何种Service,用户根据serviceName作为key查找对应的的服务,当第一次获取时,创建对象后并将对象存入map中,下次使用时只要从map中取出即可。

总结

上一篇 下一篇

猜你喜欢

热点阅读