理解Spring IOC概念及如何降低代码耦合度
什么是IOCIOC(Inversion of Control) 控制反转,是spring中一个重要的特性,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。那么控制什么的的权利被反转了呢,我们知道在写代码的过程中,经常会出现两个对象之间出现依赖关系,当A对象依赖B对象时,我们通常在A对象中通过new的方式来创建它的依赖对象B,而控制反转之后,对于对象的创建权被托付给IOC容器了.
理解Spring IOC概念及如何降低代码耦合度
什么是IOC
IOC(Inversion of Control) 控制反转,是spring中一个重要的特性,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。那么控制什么的的权利被反转了呢,我们知道在写代码的过程中,经常会出现两个对象之间出现依赖关系,当A对象依赖B对象时,我们通常在A对象中通过new的方式来创建它的依赖对象B,而控制反转之后,对于对象的创建权被托付给IOC容器了,也就是这些对象由容器来产生,而不是对象在需要的时候再去创建自己的依赖对象。
举例来理解IOC,一个家庭的组建需要夫妻两个,某种意义上,我们可以说两者之间存在依赖关系。传统方式就是,当我需要组建一个家庭时,我自己去找对象,自己去组建家庭,而IOC方式就是将找对象的权利委托给爸爸妈妈,当我一出生时,爸爸妈妈就为我指腹为婚,为我找好了对象。
IOC如何降低了代码之间的耦合度
从传统方式到IOC一步步解耦
第一步转变 直接new对象---->面向接口编程
最开始我们创建一个对象是采取new对象的方式,但这样不可以实现多态,比如我创建一个person对象,里面有一个eat(Apple apple)方法,那么调用这个eat方法的类,需要传入苹果(Apple)对象,之后我的这个方法改成吃梨子了,这个方法又改成eat(Pear pear)了,调用eat方法的类,又需要把之前的苹果改成梨子,扩展性差,于是出现了面向接口编程,我在eat方法里面传入水果(Fruit)接口,之后苹果,梨只需要实现接口即可,调用eat方法的类,想吃梨子就传入梨子,想吃苹果传入苹果即可。
第二步转变 面向接口编程 -----> 工厂模式
面向接口编程后,解决接口和实现类之间的耦合
在面向接口编程中我们常常会出现这样的代码UserDao userDao = new UserDaoImpl(); 假设现在不用这个UserDaoImpl了,而改用UserDao的另一个实现类UserDaoImpl2,UserDao userDao = new UserDaoImpl()需要改为UserDao userDao = new UserDaoImpl2(),这样也就是接口和实现类出现了耦合。
工厂模式如何去解决耦合问题呢 ---- 不让接口和实现类产生关系,而是找一个中间人,也就是工厂,实现类必须要从工厂中取出来。工厂的意思也就是一个批量制造同样规格(规格也就是接口类所提供好的规范)类的类。
工厂类:
class BeanFactory {
public static UserDao getUserDao() {
return new UserDaoImpl();
}
public static StudentDao getStudentDao() {
return new StudentDaoImpl();
}
}
UserDao userDao = new UserDaoImpl —> UserDao userDao = BeanFacotry.getUserDao();
StudentDao studentDao = new StudentDaoImpl ----> StudentDao studentDao = BeanFacotry.getStudentDao();
这样的话,如果userDao变成了需要UserDaoImpl1,studentDao变成了需要StudentDaoImpl1,我只需要去BeanFactory中改对应的getUserDao和getStudentDao方法即可。这样实际上就是从改多个类变成了改BeanFacotry一个方法,这样接口类和工厂类产生了耦合。
第三步转变 工厂模式 ----> 工厂模式+反射+配置文件(IOC的底层实现)
为了能解决接口类和工厂类的耦合,是不是也就是要解决
public static UserDao getUserDao() {
return new UserDaoImp();
}
这个方法中只能返回UserDaoImpl或者UserDaoImpl1的问题,我们希望他可以根据我们的需要返回需要的UserDaoImpl,如何解决?
配置xml文件 — 指定需要返回的UserDaoImpl
<bean id="userDao" class="**.UserDaoImpl">
工厂类
class BeanFactory {
public static UserDao getUserDao(String id) {
// String className = 解析配置文件xml 拿到id对应的class
// 反射
class clazz = class.forName(className);
return clazz.newInstance();
}
}
这样的话如果我们需要改UserDao的实现类的类型,我们可以直接在配置文件中修改,就不用改代码啦!
Spring中DI概念
DI:依赖注入,前提是必须要有IOC的环境,Spring管理这个类的时候将类依赖的属性注入进来
我们在写代码的时候知道,对象和对象之间经常会存在依赖关系,当我们使用了IOC将对象的创建权交给spring之后,spring在创建对象的同时一定也要将对象相应的依赖同时创建好,否则创建的这个对象就是一个功能不完善的对象,那么依赖注入的这个过程就是它的另一个特性DI(依赖注入)
更多推荐
所有评论(0)