在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的
方法通过读取配置文件,把这些对象创建出来 并存起来。在接下来的使用的时候,直接拿过来用就好了。
那么,这个读取配置文件,创建和获取三层对象的类就是工厂。
工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。
原来:
我们在获取对象时,都是采用 new 的方式。是主动的。
现在:
我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的
这种被动接收的方式获取对象的思想就是控制反转,它是 spring 框架的核心之一。明确 ioc 的作用:
削减计算机程序的耦合(解除我们代码中的依赖关系)
举例说明使用工厂模式解耦通过模拟一个保存用户账户:
他的service层如下:
public interface IAccountService {
/**
* 模拟保存
*/
void saveAccount();
}
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao = new AccountDaoImpl();
public void saveAccount() {
//业务层调用持久层
accountDao.saveAccount();
}
}
Dao层如下:
public interface IAccountDao {
void saveAccount();
}
public class AccountDaoImpl implements IAccountDao {
/**
* 账户的持久层实现类
*/
public void saveAccount() {
System.out.println("保存了账户");
}
}
模拟表现层:
public class Client {
public static void main(String[] args) {
IAccountService ac = new AccountServiceImpl();
ac.saveAccount();
}
}
此时可以发现表现层调用业务层,采用new 的方式,业务层调用持久层也使用new,这两处发生依赖,需要解耦。我们采用工厂模式解耦建立一个BeanFactory类
/** bean在计算机英语中有可重用组件的含义
* javaBean:用Java语言编写的可重用组件
* JavaBean不等于实体类 ,javebean远大于实体类
* 他就是创建我们的service和dao对象
* 第一个需要一个配置文件来配置service和dao
* 配置的内容:全限定类名(key value的形式)
* 第二个:通过配置文件的内容,反射创建对象
*
* 我们的配置文件可以选择xml或者properties
* @author Aaron_Kitty
* @Date 2020/3/13 16:12
*/
public class BeanFactory {
/**定义一个properties对象
*
*/
private static Properties props;
//使用静态代码块为properties赋值
static {
//实例化对象
props = new Properties();
//获取properties流对象
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
props.load(in);
} catch (IOException e) {
throw new ExceptionInInitializerError("初始化properties失败");
}
}
public static Object getBean(String beanName){
Object bean = null;
String beanPath = props.getProperty(beanName);
try {
bean = Class.forName(beanPath ).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return bean;
}
}
对应业务层和表现层的new改成
private IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");
IAccountService ac = (IAccountService) BeanFactory.getBean("accountService");
以上的工厂解耦代码,实际上是采用多例对象的方式,
for (int i = 0; i < 5; i++) {
IAccountService ac = (IAccountService) BeanFactory.getBean("accountService");
System.out.println(ac);
}
/*for循环输出结果
com.tiger.service.impl.AccountServiceImpl@74a14482
com.tiger.service.impl.AccountServiceImpl@1540e19d
com.tiger.service.impl.AccountServiceImpl@677327b6
com.tiger.service.impl.AccountServiceImpl@14ae5a5
com.tiger.service.impl.AccountServiceImpl@7f31245a*/
我们可以进一步优化采取单例模式。
public class BeanFactory {
/**定义一个properties对象
*
*/
private static Properties props;
private static Map<String,Object> map;
//使用静态代码块为properties赋值
static {
try{
//实例化对象
props = new Properties();
//获取properties流对象
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
props.load(in);
//实例化容器
map = new HashMap<String,Object>();
//取出props中所有的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和创建的对象存入map中,从而实现单例
map.put(key,value);
}
}
catch (IOException e) {
throw new ExceptionInInitializerError("初始化properties失败");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Object getBean(String beanName){
return map.get(beanName);
}
}