关于解耦知识的学习
一:耦合发生场景及解耦合思路
可以看到在jdbc注册驱动的时候是通过new Driver()来完成注入的.
如果没有Driver的jar包的话则编译期间就会报错,如果改成classs.forname(com.mysql.jdbc.Driver)通过反射来启动,则能解除耦合,而这套程序可独立作为工具类或封装好的方法来使用.这既是解耦合的好处.
引入解耦的概念
解耦:降低程序的依赖关系
也就是实际开发中应做到编译时不依赖,运行时依赖.
一.将通过3个过程来分析解耦
1.这是目录结构
第一个阶段:
service层
public class AccountServiceImpl implements IAccountService {
private IAccountDao id = new AccountServiceImpl();
@Override
public void add() {
id.insert();
}
}
dao层
public class AccountDaoImpl implements IAccountDao {
@Override
public void insert() {
System.out.println("新增用户入库");
}
}
调用业务
public class Mooo {
public static void main(String[] args) {
IAccountService ia = new AccountServiceImpl();
ia.add();
}
}
从第一个阶段可以看到service层和调用方都存在new Object()的过程,会在一个耦合关系,如果new的jar不存在的情况下会在编译的时候报错.
第二个阶段
经过代码的优化可以解除耦合关系
service层
public class AccountServiceImpl implements IAccountService {
private IAccountDao id = (IAccountDao) BeanFactory.getBean("accountDao");
@Override
public void add() {
id.insert();
}
}
调用业务
public class Mooo {
public static void main(String[] args) {
IAccountService ia = (IAccountService) BeanFactory.getBean("accountService");
ia.add();
}
}
新增BeanFactory类来解耦
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) {
e.printStackTrace();
}
}
public static Object getBean(String name) {
Object bean=null;
try {
String beanPath = props.getProperty(name);
bean = Class.forName(beanPath).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return bean;
}
}
新增配置文件bean.properties
accountService=com.sitech.service.impl.AccountServiceImpl
accountDao=com.sitech.dao.impl.AccountDaoImpl
此时可以看到原本耦合的地方都已经解耦合了,是不是此时已经结束了呢?
并没有,我们发现在BeanFactory的方法中有一个newInstance()的过程,这就意味着每一次调用这个方法都会新建一个实例,这样的话会影响一个效率问题.
有没有办法让它变成单例呢?
`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
此时进入第三个阶段
仅对beanFactory作修改
public class BeanFactory {
//定义一个properties对象
private static Properties props;
private static Map<String,Object> beanMap;
// 使用静态代码块为properties赋值,只在类加载的时候加载一次
static {
// 实例化对象
props= new Properties();
beanMap = new HashMap<String,Object>();
// 获取properties文件的流
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
props.load(in);
Enumeration keys = props.keys();
while(keys.hasMoreElements()){
String key = keys.nextElement().toString();
String beanPath = props.getProperty(key);
Object obj = Class.forName(beanPath).newInstance();
beanMap.put(key,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object getBean(String name) {
return beanMap.get(name);
}
可以看到在类加载的时候就已经将properties配置文件中所有的键值对都已经加载至容器.取值可以直接从容器中获取.完成优化~