(3) 为实现类定义初始化工厂类
class ImageLoaderFactory {
private static ImageLoader mImageLoader;
private ImageLoaderFactory() {
//no instance
}
/**
* @return
*/
public static ImageLoader createImageLoader(String implClass) {
if (mImageLoader == null) {
mImageLoader = createImageLoaderWithClassName(implClass);
}
return mImageLoader;
}
/**
* 此处使用类反射, 所有implClass都不能混淆, 类名必须keep:  {@code -keep class a.b.c.ImplClass}
* @param implClass 实现类有: FrescoImageLoader, GlideImageLoader, PicassoImageLoader, UILImageLoader
* @return
*/
private static ImageLoader createImageLoaderWithClassName(String implClass) {
try {
Class klass = Class.forName(implClass);
Constructor constructor = klass.getDeclaredConstructor();
if (constructor == null) {
throw new RuntimeException(implClass + " 的实现类必须有一个无参构造方法 !");
}
boolean isAccessible = constructor.isAccessible();
constructor.setAccessible(true);
Object obj = constructor.newInstance();
constructor.setAccessible(isAccessible);
if ( !(obj instanceof ImageLoader) ) {
throw new RuntimeException(implClass + "必须实现" + ImageLoader.class.getName() + "接口");
}
ImageLoader imageLoader = (ImageLoader) obj;
return imageLoader;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
  (4) 要使用ImageLoader, 直接用工厂类创建即可, 我们只需要知道实现类的名称, 其它细节都不需要知道. 实现类都是高度内聚, 外部完全不知道其内部的逻辑. 外部只需要调用接口的方法实现业务逻辑即可. 下面是ImageLoader及其相关实现的整体结构:


  
接口与实现分离, 隐藏实现

  (5) 下面是使用工厂类创建ImageLoader实现的代码
import android.content.Context;
public final class ImageManager {
private static String TAG = "ImageManager";
private static ImageLoader sImageLoader;
private ImageManager() {
//no instance
}
public static void init(Context appContext) {
if (sImageLoader != null) {
throw new IllegalStateException(TAG + " already initalized");
}
sImageLoader = ImageLoaderFactory.createImageLoader("com.stone.app.manager.imageloader.internal.FrescoImageLoader");
sImageLoader.init(appContext);
}
public static ImageLoader getImageLoader() {
return sImageLoader;
}
}
  总结:
  将接口和实现类分离, 接口和实现分别放在单独的包中, 并且实现类定义为包私有的 (即类没有修饰符).
  定义工厂类, 使用反射初始化实现类.
  注意混淆的时候不能混淆实现类的类名, 因为其初始化使用了反射.