通常我们在使用简单工厂模式的时候会由创建方法create通过传入的参数来判断要实例化哪个对象,就像下面这样:
-
public
static
class ImageSelectFactory {
-
public static IImageSelect createIImageSelect(ImageSelectClientMode mode) {
-
IImageSelect imageSelect =
null;
-
if (mode == ImageSelectClientMode.COLLECTION_IMAGE) {
-
imageSelect =
new CollectionImage();
-
}
else
if (mode == ImageSelectClientMode.LOCAL_PHOTO) {
-
imageSelect =
new LocalPhoto();
-
}
else
if (mode == ImageSelectClientMode.WORKS_IMAGE) {
-
imageSelect =
new WorksImage();
-
}
else
if (mode == ImageSelectClientMode.TAKE_PHOTO) {
-
imageSelect =
new TakePhoto();
-
}
else
if (mode == ImageSelectClientMode.SUPER_IMAGE_LIB) {
-
imageSelect =
new SuperImageLib();
-
}
-
return imageSelect;
-
}
-
}
这里面定义了5个IImageSelect接口的子类,通过定义好的泛型ImageSelectClientMode来决定实例化哪个子类,现在遇到这么一个问题,如果添加到第6个子类的话,那就必须要更改ImageSelectFactory类以及枚举ImageSelectClientMode,可能你会说“改一下又何妨?”,虽不说影响不影响什么开闭设计原则,但是有个情况你可成想到,你这个类要打包发布给别人用呢?别人在没有源码的情况下如何扩展呢?这里就需要我们动态的通过配置文件来加载实现类了。
实现的基本思路为:通过读取本地的.properties文件来获取我们需要实例化的类,然后通过反射来生成对象,这样当你把发布出去的时候,使用者只用更改配置文件就可以让工厂去实例化自己后来才写的实现类,我们看看实现方式:
ImageSelectClient.properties:
-
COLLECTION_IMAGE=com.kongfuzi.student.support.bitmap.select.CollectionImage
-
LOCAL_PHOTO=com.kongfuzi.student.support.bitmap.select.LocalPhoto
-
WORKS_IMAGE=com.kongfuzi.student.support.bitmap.select.WorksImage
-
TAKE_PHOTO=com.kongfuzi.student.support.bitmap.select.TakePhoto
-
SUPER_IMAGE_LIB=com.kongfuzi.student.support.bitmap.select.SuperImageLib
-
public
static
class ImageSelectFactory {
-
public static IImageSelect createIImageSelect(String type) {
-
IImageSelect mIImageSelect;
-
-
//实例化Properties对象,用于读取.properties
-
Properties properties =
new Properties();
-
InputStream is =
null;
-
try {
-
is = ImageSelectClient.class.getResourceAsStream(
"ImageSelectClient.properties");
-
//装载ImageSelectClient.properties文件
-
properties.load(is);
-
}
catch (Exception e) {
-
e.printStackTrace();
-
}
finally {
-
try {
-
is.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
-
try {
-
//根据key获取value,value即为将要实例化的类
-
Class<?> aClass = Class.forName(properties.getProperty(type));
-
//使用反射进行实例化
-
mIImageSelect = (IImageSelect) aClass.newInstance();
-
}
catch (ClassNotFoundException e) {
-
e.printStackTrace();
-
}
catch (InstantiationException e) {
-
e.printStackTrace();
-
}
catch (IllegalAccessException e) {
-
e.printStackTrace();
-
}
-
return mIImageSelect;
-
}
-
}
这样,我们就可以随便实现子类,然后在.properties文件中添加对应的包路径,然后通过ImageSelectFactory就可以进行实例化了。