一、程序耦合
耦合:程序间的依赖关系,包括类之间的依赖和方法间的依赖
以一个jdbc工程为例
通过上图可以发现,采用硬编码的方式,当项目工程中未引入mysql驱动依赖时,程序在运行期会报错,说明程序存在编译期依赖,耦合度较高,在实际开发中,常常不采用这种方式。
耦合分类
解耦:降低程序间的依赖关系,在实际开发时,做到编译期不依赖,运行期依赖
解耦思路:
使用反射创建对象,而避免使用new关键字
通过读取配置文件来获取要创建的对象的全限定类名
二、工厂模式解耦
bean:在计算机英语中,有可重用组建的含义
Javabean:用Java语言编写的可重用组件
BeanFactory:创建Bean对象的工厂
(1) 需要一个配置文件来配置service和dao, 配置内容:唯一标识=全限定类名(key=value)
(2) 通过读取配置文件中的配置的内容,反射创建对象
调用时
结合之前的分析,使用反射和读取配置文件实现了beanfactory,但是在实际开发中,service层和dao层往往是单例的,故在创建service层和dao层时往往使用单例设计模式
public class Beanfactory {
//定义一个Properties对象
private static Properties props;
//定义一个Map,用于存放要创建的对象,把他称之为容器
private static Map<String, Object> beans;
//使用静态代码块为Properties对象赋值
static {
try {
//实例化Properties对象
props = new Properties();
//获取properties文件的流对象
InputStream in = Beanfactory.class.getClassLoader().getResourceAsStream("bean.properties");
props.load(in);
//实例化容器
beans = new HashMap<String, Object>();
//取出配置文件中所有的key
Enumeration<Object> keys = props.keys();
//遍历枚举
while(keys.hasMoreElements()) {
//取出每个key
String key = keys.nextElement().toString();
//根据key获取value
String beanPath = props.getProperty(key);
//反射创建对象
Object value = Class.forName(beanPath).newInstance();
//把key和value存入容器中
beans.put(key, value);
}
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化properties失败");
}
}
public static Object getBean(String beanName) {
return beans.get(beanName);
}
}
细节
在单例模式中,类成员变量会存在线程安全问题:当一个用户修改了该成员变量,后面用户看到的是改过的数据,所以通常将变量写在成员方法中,这样就可以达到想要的。