通过工厂模式模拟IOC思想,实现程序解耦
程序的耦合及解耦
程序的耦合
耦合:程序间的依赖关系(过于依赖,造成高耦合)
- 类之间的依赖
- 方法间的依赖
解耦:降低程序间的依赖关系
实际开发中:编译期不依赖,运行时才依赖
解耦的思路:
- 使用反色创建对象,而避免new关键字
- 通过读取配置文件来获取要创建的对象全限定类名
通过工厂模式解耦
通过一个创建bean的对象工厂来实现解耦,即通过工厂来创建service和dao对象
- 需要一个配置文件来配置service和dao
- 读取配置文件中配置的内容,通过反射创建对象
配置文件:xml、properties
通过一个转账的案例对解耦做出一个阐述,其实这个过程就是在模拟spring
BeanFactory 类
package com.one.factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class BeanFactory {
//定义一个Properties对象
private static Properties properties;
//定义一个Map,用于存放我们要创建的对象,我们把它称之为容器
private static Map<String,Object> beans;
//使用静态代码块为Properties对象赋值
static {
//实例化对象
properties = new Properties();
//获取properties对象的流对象
InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
properties.load(inputStream);
//实例化容器
beans = new HashMap<String, Object>();
//取出配置文件中所有的key
Enumeration<Object> keys = properties.keys();
//遍历枚举
while (keys.hasMoreElements()){
//从枚举中取出所有的key
String key = keys.nextElement().toString();
System.out.println(key);
//通过key,取出配置文件中对应的值,即全限定类名
String beanPath = properties.getProperty(key);
//通过全限定类名用反射的方式创建实例
Object instance = Class.forName(beanPath).newInstance();
//将key和实例存入map集合中,即存入beans中
beans.put(key,instance);
}
} catch (IOException e) {
e.printStackTrace();
//初始化异常
throw new ExceptionInInitializerError("读取bean配置文件出错");
} catch (Exception e) {
e.printStackTrace();
System.out.println("在遍历keys时,可能出现了异常");
}
}
/**
* 通过beanName获取对象(单例)
* @param beanName
* @return
*/
public static Object getBean(String beanName){
Object bean = beans.get(beanName);
return bean;
}
}
properties文件:用于模拟在xml中配置bean
accountService=com.one.service.impl.AccountServiceImpl
accountDao=com.one.dao.impl.AccountDaoImpl
# 此处顺序颠倒会出现异常,在读取配置文件时,会逐个向枚举中添加key,类似于栈的存储方式
# 因此在遍历keys时,在先读取到的是最后面的(accountDao)
# 在创建实例时,accountDao会优先于accountService加载
# 当在之后加载accountService时,accountDao已经存在,accountService便能正常获得accountDao
# 在使用accountService时,也就不会报accountDao的空指针异常
//通过工厂获取对象实例
AccountService accountService = (AccountService) BeanFactory.getBean("accountService");
private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");