通常我们在使用简单工厂模式的时候会由创建方法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就可以进行实例化了。