依赖注入的理解

先说结论
我的session只是一种简化形式 或者说 只利用了一部分特性 个人认为对于游戏开发已经足够了

依赖注入就是一种代码的组织形式
可以把他们当做一个一个模块
每个模块之间看不到彼此
然后有一个中间商
他来负责把模块组合起来
模块之间就是靠接口来对接

举个例子就是 你有一个锯齿 (齿轮就是接口)
想让他转起来是不是需要另一个锯齿?
旧方法 让这个锯齿把另一个new出来 或者自己去哪哪哪找到另一个齿轮 然后把他拼自己身上
新方法 来一个中间商new一个新齿轮或找到齿轮 然后把两者给拼上

中间商new新锯齿 并且拼上这个过程 理论上 不应该由任何一个锯齿来操作
所以中间商的角色就出来了
你想得到某个模块的引用和功能 不应该由你自己来操作 因为你只是个齿轮

当你是背包session的时候 你不需要关心去哪里拿技能session
系统已经给你准备好了 至于给你的是哪个技能session 你不需要操心

假如说 你有一个技能模块(skillsession) 但是你发现 这个模块写的不太好 想重写 可是又不想把所有模块都整瘫痪
你可以新建一个skillsesssion 和 原来的接口一致
然后你想测试背包模块引用技能模块时有没有问题 把新技能模块注入进去就可以了 无缝切换模块 而且其他都不受影响
这个过程背包模块是不用动的
软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。

软件系统在引入IOC容器之后,这种情形就完全改变了,如图2所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。

所谓依赖,举个例子说明,一个类Person,另一个类Car,如果Person的某个方法比如说drive,需要引用Car,则称Person类依赖于 Car类,延伸到对象,这种依赖关系依然成立,比如说Person类的对象boy依赖于Car类的对象toyota。再讲讲这个drive方法的实现,假定代码如下:
Public Person{

public void drive(){
Car toyota=new Car(“TOYOTA”);
toyota.挂档;
toyota.踩油门;
toyota.打方向;
}
}
这其中的依赖关系,就导致了对象boy需要负责对象toyota的创建,甚至是整个生命周期的管理,而这样显然会带来耦合度高,不易维护等缺点,比如说要让这个男孩驾驶一辆Audi,则还需要修改类Person的代码。
因此在java的设计理论中就提出了一条非常著名的原则,依赖倒转原则(Dependence Inversion),其核心思想就是要将这种具体类之间的依赖,尽量转换成抽象依赖,也就是说类Person应该依赖于抽象类ICar,而不是具体的类 Car,这里java就大力推荐了抽象和接口的使用,至于抽象和接口之间的区别,任何一本JAVA书籍都有介绍,这里就不再说了。
这个依赖倒转原则在设计模式也体现得非常多,比如说工厂模式和构建模式,个人认为控制反转IoC,其实也可以认为是实现这个原则的一种设计模式。控制反转,其中的控制这个词一直不太理解是什么意思,不过控制反转的另外一种说法也就是依赖注入(dependence injection),个人觉得更易于理解。还是以上文的boy与toyota为例,其核心就是要将boy依赖的对象toyota注入到boy中去,而无需boy自己去引用toyota,这个注入的过程,通常是由一个控制程序来完成的,无需对象去关心,举例如下:
Public Person{
private ICar car;
public Person(ICar onecar){
car=onecar;
}
public void drive(){
car.挂档;
car.踩油门;
car.打方向;
}
}

这个时候,进行注入并且调用的过程,就很简单了,如下:
Toyota toyota=new Toyota();
Person boy=new Person(toyota);
boy.drive();

注:这里我们假定,Toyota类是ICar接口类的一个具体实现。
这个例子就演示一个最简单的注入方式的例子,也就是构造子方式注入,通过将依赖对象注入到对象的构造子中来实现。另外还有一种常用的注入方式,就是属性方式注入,意思就是通过将依赖对象注入到对象的属性中来实现,还是以boy和toyota的例子说明,如下:

Public Person{
private ICar car;
public Person(){
}
public void drive(){
car.挂档;
car.踩油门;
car.打方向;
}
public ICar getCar(){
return this.car;
}
public void setCar(ICar onecar){
car=onecar;
}
}

这个时候,进行注入并且调用的过程,就变成如下所示:
Toyota toyota=new Toyota();
Person boy=new Person();
boy.setCar(toyota);
boy.drive();

至此依赖注入的概念应该比较清楚了,再来看看在Spring中如何实现IoC的,看看Spring如何作为一个成熟的IoC容器,Spring中其实主要通过两个概念来实现IoC,首先通过XML配置文件,将对象和依赖对象都配置到某个XML文件中,当然该XML文件需要符合Spring指定的规范,然后通过架构中的BeanFactroy类,来自动实现上文所述注入过程,还是以boy与toyota为例,如下:
首先,Person类还是一样的,

最后,调用的过程,就变成如下:

BeanFactory factory=new XmlBeanFactory(“bean.xml”);
Person boy=(Person )factory.getBean(“onePerson”);
boy.drive();

A类和B类,如果A要用到B
在A类中加一个setB()就OK了,再通过spring的IOC容器实例化好的对象用属性注入就OK了

 我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值