谈谈Java接口与实现的分离以及隐藏实现

发表于:2017-1-16 11:14

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:元亨利贞o    来源:51Testing软件测试网采编

分享:
  (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;
}
}
  总结:
  将接口和实现类分离, 接口和实现分别放在单独的包中, 并且实现类定义为包私有的 (即类没有修饰符).
  定义工厂类, 使用反射初始化实现类.
  注意混淆的时候不能混淆实现类的类名, 因为其初始化使用了反射.
  有一个设计模式也是分离接口和实现并使其各自独立变化, 那就是桥接模式. 具体可以参考Android中的Window和Context的设计. 关于动态扩展和分离接口和实现, 可以参考《在Android上使用SPI机制》
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号