加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

工厂模式的升级 IOC 依赖注入 控制反转

发布时间:2020-12-13 23:01:54 所属栏目:百科 来源:网络整理
导读:依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在S

依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。


总结

(1)也许有人说,IoC和工厂模式不是一样的作用吗,用IoC好象还麻烦一点。

举个例子,如果用户需求发生变化,要把Chinese类修改一下。那么前一种工厂模式,就要更改Factory类的方法,并且重新编译布署。而IoC只需 要将class属性改变一下,并且由于IoC利用了Java反射机制,这些对象是动态生成的,这时我们就可以热插拨Chinese对象(不必把原程序停止 下来重新编译布署,java特性 需要重新编译

(2)也许有人说,即然IoC这么好,那么我把系统所有对象都用IoC方式来生成。

注意,IoC的灵活性是有代价的:设置步骤麻烦、生成对象的方式不直观、反射比正常生成对象在效率上慢一点。因此使用IoC要看有没有必要,我认为比较通用的判断方式是:用到工厂模式的地方都可以考虑用IoC模式。

(3)在上面的IoC的方式里,还有一些可以变化的地方。比如,bean.xml不一定要放在项目录下,也可以放在其他地方,比如cn.com.chengang.spring包里。不过在使用时也要变化一下,如下所示:

new FileSystemXmlApplicationContext("src/cn/com/chengang/spring/bean.xml");
另外,bean.xml也可以改成其他名字。这样我们在系统中就可以分门别类的设置不同的bean.xml。

(4)关于IoC的低侵入性

什么是低侵入性?如果你用过Struts或EJB就会发现,要继承一些接口或类,才能利用它们的框架开发。这样,系统就被绑定在Struts、EJB上 了,对系统的可移植性产生不利的影响。如果代码中很少涉及某一个框架的代码,那么这个框架就可以称做是一个低侵入性的框架。

Spring的侵入性很低,Humen.java、Chinese.java等几个类都不必继承什么接口或类。但在ClientTest里还是有一些 Spring的影子:FileSystemXmlApplicationContext类和ctx.getBean方式等。
现在,低侵入性似乎也成了判定一个框架的实现技术好坏的标准之一。

1、如下图所示有三个类,Human(人类)是接口,Chinese(中国人)是一个子类,American(美国人)是另外一个子类。
源代码如下:
java代码packagecn.com.chengang.spring;
publicinterfaceHuman{
voideat();
voidwalk();
}

packagecn.com.chengang.spring;
publicclassChineseimplementsHuman{
/*(非Javadoc)
*@seecn.com.chengang.spring.Human#eat()
*/
publicvoideat(){
System.out.println("中国人对吃很有一套");
}

/*(非Javadoc)
*@seecn.com.chengang.spring.Human#walk()
*/
publicvoidwalk(){
System.out.println("中国人行如飞");
}
}

packagecn.com.chengang.spring;
publicclassAmericanimplementsHuman{
/*(非Javadoc)
*@seecn.com.chengang.spring.Human#eat()
*/
publicvoideat(){
System.out.println("美国人主要以面包为主");
}

/*(非Javadoc)
*@seecn.com.chengang.spring.Human#walk()
*/
publicvoidwalk(){
System.out.println("美国人以车代步,有四肢退化的趋势");
}
}
2、对以上对象采用工厂模式的用法如下

创建一个工厂类Factory,如下。这个工厂类里定义了两个字符串常量,所标识不同的人种。getHuman方法根据传入参数的字串,来判断要生成什么样的人种。
java代码packagecn.com.chengang.spring;
publicclassFactory{
publicfinalstaticStringCHINESE="Chinese";
publicfinalstaticStringAMERICAN="American";

publicHumangetHuman(Stringethnic){
if(ethnic.equals(CHINESE))
returnnewChinese();
elseif(ethnic.equals(AMERICAN))
returnnewAmerican();
else
thrownewIllegalArgumentException("参数(人种)错误");
}
}
下面是一个测试的程序,使用工厂方法来得到了不同的“人种对象”,并执行相应的方法。
java代码packagecn.com.chengang.spring;
publicclassClientTest{
publicstaticvoidmain(String[]args){
Humanhuman=null;
human=newFactory().getHuman(Factory.CHINESE);
human.eat();
human.walk();
human=newFactory().getHuman(Factory.AMERICAN);
human.eat();
human.walk();
}
}
3、采用Spring的IoC的用法如下:

在项目根目录下创建一个bean.xml文件
xml代码<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<beanid="Chinese"class="cn.com.chengang.spring.Chinese"/>
<beanid="American"class="cn.com.chengang.spring.American"/>
</beans>
修改ClientTest程序如下:
java代码packagecn.com.chengang.spring;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
publicclassClientTest{
publicfinalstaticStringCHINESE="Chinese";
publicfinalstaticStringAMERICAN="American";

publicstaticvoidmain(String[]args){
//Humanhuman=null;
//human=newFactory().getHuman(Factory.CHINESE);
//human.eat();
//human.walk();
//human=newFactory().getHuman(Factory.AMERICAN);
//human.eat();
//human.walk();

ApplicationContextctx=newFileSystemXmlApplicationContext("bean.xml");
Humanhuman=null;
human=(Human)ctx.getBean(CHINESE);
human.eat();
human.walk();
human=(Human)ctx.getBean(AMERICAN);
human.eat();
human.walk();
}
}

从这个程序可以看到,ctx就相当于原来的Factory工厂,原来的Factory就可以删除掉了。然后又把Factory里的两个常量移到了ClientTest类里,整个程序结构基本一样。再回头看原来的bean.xml文件的这一句: <bean id="Chinese" class="cn.com.chengang.spring.Chinese"/> id就是ctx.getBean的参数值,一个字符串。class就是一个类(包名+类名)。然后在ClientTest类里获得Chinese对象就是这么一句human = (Human) ctx.getBean(CHINESE); 因为getBean方法返回的是Object类型,所以前面要加一个类型转换

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读