声明:初识框架的理解与思考,错误之处,欢迎指正
控制反转:
传统的创建对象过程是自己new对象,并调用方法
Student student = new Student();
course c = new JavaCourse();
course o = new HtmlCourse();
student.learnHtml(o);
student.learnJava(c);
这个 自己 指的是"程序/代码"自己 而不是指程序员
上面代码 有一个学生类,course课程接口 JavaCourse和HtmlCourse类继承与course 并各自有learnJava和learnHtml方法
若 student想要调用learnJava()或learnHtml方法,就必须先创建JavaCourse或HTMLcourse对象
可以说,student对象依赖JavaCourse对象 才能使用learnJava方法 . 这时这两个对象之间就产生了耦合关系
使用IOC解决了自己(程序/代码)new对象的过程 当程序需要对象的时候,直接去IOC容器里拿 IOC容器已经有了需要的对象
至于IOC容器里的对象,还是 程序员 写好的代码
从自己(程序/代码) new出对象到 从容器中被动接受对象 这个转变的过程就叫 控制反转
从程序控制对象(new的过程), 变成了容器控制对象(控制谁可以使用对象) 这就是反转
IOC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
由于有了IOC容器 对象不再直接的与另一个对象(依赖对象)发生关系,而是通过容器间接发生关系,这就达成了松耦合的目标
现在,由于程序是被动的接受对象 这个被动接受的过程就是 注入 而且,注入的是程序需要依赖的对象 于是就叫依赖注入
(其实这里有个问题,
1.就算是有了一个中间容器, 一个对象还是需要另一个对象才能完成一个方法 , 怎么就松耦合了 )
问题的一个解释
作者:Ziphwy
链接:https://www.zhihu.com/question/27053548/answer/85060703
来源:知乎
举个例子,比如你写
Apple apple = new Apple();
People people = new People();
people.eat(apple);
然后有一天,客户说不想吃Apple了
给我改成吃Orange,然后你打开源文件
Orange orange = new Orange();
People people = new People();
people.eat(orange);
再重新编译
再一天,客户又觉得不好,要Peach了
Peach peach = new Peach();
People people = new People();
people.eat(peach);
再重新编译
………
然后你在客户的需求下崩溃了
倘若用spring
Fruit fruit = (Fruit)beanFactory.getBean("fruit");
People people = (People)beanFactory.getBean("people");
people.eat(fruit);
这样使用了接口Fruit,你只需要在xml文件配置,更换fruit的bean,无需改变源代码。对于people也如此。
会发现,我们在这种设计下会少维护了很多代码,达到这样的效果的原因是因为,Fruit和People没有参杂在一起(?),没有谁调用了谁等等,实际上就是没有耦合,他们的关系由接口代替表示了。
使用spring解决了什么问题
使用Spring之后,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。
所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己(程序)把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了(?),它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象(程序)找相应的依赖对象并注入,而不是由对象(程序)主动去找(new)。
现实例子
想到一个现实例子,比如说租房,原本的方式是自己去满大街的找房东,找房子,使用了spring IOC容器就好比有了一个中介,中介已经拥有了很多房子,不需要自己再去找房东,而只需要去找中介,让中介给自己合适的房子.
这样,自己和房东的关系就没有了,变成了自己和中介的关系,所以,达成了松耦合的目的
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
更多补充
作者:OneNoodle
链接:https://www.zhihu.com/question/23277575/answer/24259844
来源:知乎
,甲乙可以在对方不真实存在的情况下独立存在,而且保证不交易时候无联系,想交易的时候可以很容易的产生联系。甲乙交易活动不需要双方见面,避免了双方的互不信任造成交易失败的问题。因为交易由第三方来负责联系,而且甲乙都认为第三方可靠。那么交易就能很可靠很灵活的产生和进行了。
问:有点小问题,如果是甲方要袜子,那么他也必须依赖于一个卖袜子的人,这之间就有联系了,也就是说甲方也是依赖于乙方的,因为如果乙方没有卖袜子的话,甲方也就买不到袜子,自然也就没法继续进行,这怎么就解隅了呢??
答:是解耦的,平时new A()时候是要import包地址的,这就已经写死了,以后这个引用就死死的指向了那个类,想改变很麻烦,用ac.getbean(“A”)就没引入包,也就是所谓的不依赖 (就是跟那类A没关系),它只从容器找那个叫A的类,至于你给我的是啥,看容器中咋配置。举了例子:比如说是个很常用的dao类,开始你new的很开心,万一以后需求大改,数据库mysql换db2了,这个dao文件基本就得重写,如果这个类已经封装编译为class文件,不能改了怎么办。又或者你实例化了一个常用接口。原来那个实现类A不好,要换成B做他的实现类,重写他的方法。你就得把项目中所有实例化的地方都找出来,再改成B(大项目用了很多的话你就一个一个改类似,万一漏了就是不小的bug)。用ioc就没 这个麻烦,直接在配置文件中将叫A的bean指向你新写的类就可以。所以说他依赖的乙方不是卖袜子的,而是一个中介