源码中好多使用容器实现单例模式:
public class Singleton {
private static Map<String, Object> objMap = new HashMap<String, Object>();
private Singleton() { }
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);
}
}
在程序的初始,将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对象对应类型的对象.这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了耦合度.
其实单例的核心原理都是,将构造函数私有化,并且通过静态方法获取一个唯一的实例,在这个获取中必须保证线程安全,防止反序列化导致重新生成实例对象等问题,
android源码中的单例模式
以常用的LayoutInflater为例:
通常在代码中的使用如下:
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;
}
可以看到from函数内部调用的是Context类的getSystemService(String key)方法,Context是一个抽象类,具体实现是在ContextImpl类中,
class ContextImpl extends Context {
//通过SystemServiceRegistry类来具体实现
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
}
//此类用来管理所有系统服务,可以用{@link Context#getSystemService方法来返回对应的服务
final class SystemServiceRegistry {
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}
//代码省略
//ServiceFetcher通过getService获取服务对象
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;
public CachedServiceFetcher() {
mCacheIndex = sServiceCacheSize++;
}
//获取系统服务
@Override
@SuppressWarnings("unchecked")
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
synchronized (cache) {
// Fetch or create the service.
Object service = cache[mCacheIndex]; //从缓存中读取service对象
if (service == null) {
service = createService(ctx); //第一次创建该对象
cache[mCacheIndex] = service; //该对象缓存到一个列表中
}
return (T)service;
}
}
public abstract T createService(ContextImpl ctx); //子类复写该方法用以创建服务对象
}
//1. services 容器
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
private static int sServiceCacheSize;
//2. 注册服务器
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
//3. 静态语句块 第一次加载该类时执行(只执行一次,确保实例的唯一性)
static {
//注册 LayoutInflater service
registerService(Context.NSD_SERVICE, NsdManager.class,
new CachedServiceFetcher<NsdManager>() {
@Override
public NsdManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.NSD_SERVICE);
INsdManager service = INsdManager.Stub.asInterface(b);
return new NsdManager(ctx.getOuterContext(), service);
}});
}
//4. 根据key获取对应的服务
public static Object getSystemService(ContextImpl ctx, String name) {
//根据name来获取服务
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
//代码省略
}
从以上代码中可以看到,在虚拟机第一次加载该类时,会注册各种ServiceFetcher,其中就包含了LayoutInflater service,将这些服务以键值对的形式存储在HashMap中,用户使用是只需要根据key来获取对应的
ServiceFetcher,然后通过ServiceFetcher对象的getService函数来获取具体的服务对象,当第一次获取是会调用ServiceFetcher的createService函数创建服务对象,然后将该对象缓存到一个列表中,下次再取时
直接从缓存中获取,避免重复创建对象,从而达到单例的效果.
android源码中的单例模式实现
最新推荐文章于 2022-11-05 21:20:49 发布