在做项目时,遇到需要创建DAO、Service等类的实例的时候,想到用工厂方法来运作,而简单工厂方法又有明显的缺点:
①由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;
②它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
③当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
所以考虑使用配置文件+java反射机制来动态创建类的实例,具体思路如下:
通过读取本地的.properties文件来获取我们需要实例化的类,然后通过反射来生成对象,这样当你把发布出去的时候,使用者只用更改配置文件就可以让工厂去实例化自己后来才写的实现类。
使用该方法也就解决了上述问题中:当实体增多时,工厂类需要重新编写的问题了。
先来介绍一下.properties文件
在Java中,使用一种以.properties为扩展名的文本文件作为资源文件,该类型的文件的内容格式为类似:
#注释
key=value
#为注释,ResourceBundle处理时会自动忽略,对于key=value,应用较多的是数据库的配置文件,比如这样:
#数据库配置信息 DRIVER=com.mysql.jdbc.Driver URL=jdbc:mysql://localhost:3306/cns user=test password=test
而在这里,需要记录的就是 key( 你的实体类名)=value(该类的具体路径),这里的value用于反射中forName(String className)来加载该类。
java.util.ResourceBundle
myres_zh_CN.properties
直接上代码:
import java.util.ResourceBundle; public class BeanFactory { // 加载配置文件 private static ResourceBundle bundle; static { bundle = ResourceBundle.getBundle("instance"); } /** * 根据指定的key,读取配置文件获取类的全路径; 创建对象 * */ public static <T> T getInstance(String key,Class<T> clazz) { String className = bundle.getString(key); try { return (T) Class.forName(className).newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } }
其中
bundle = ResourceBundle.getBundle("instance");
instance是我的资源文件名称,全名是instance.properties
然后再通过指定的key来获取具体的类名
bundle.getString(key)
之后利用反射来创建类的实例。