目录
一、为什么要解耦
二、示例分析
三、如何解除耦合?
四、控制反转和依赖注入-简述
一、为什么要解耦
- 内聚:软件中各个功能模块内部的功能联系
- 耦合:衡量软件中各个层/模块之间的依赖、关联的程度
- 软件设计原则:高内聚低耦合。高内聚指的是模块内部的功能联系越紧密越好,比如在"员工管理"的service中,仅仅存放与员工相关的逻辑处理。低耦合指的是尽可能降低层与层之间或者模块与模块之间的依赖关联,最好能做到解除耦合
解除耦合之后,层与层之间就没有依赖了,即使service层的代码发生了变动,也不会影响controller层和dao层的代码,这样就增强了程序的灵活性和可扩展性
二、示例分析
在该程序中,conrtroller需要调用EmpService,直接new了一个EmpServiceA对象。
EmpServiceA是EmpService的实现。
如果我们要切换service实现,比如将EmpServiceA切换为EmpServiceB,如图:
此时controller层new的对象也需要改动,如图:
此时就发现,service的代码发生了变化,controller的代码也要跟着改动。即:controller层与service层之间的代码耦合了。
三、如何解除耦合?
要想解除耦合,controller层就不能直接new service层的实现类了,一旦new了service层的实现类,这两层之间就已经耦合起来了。
所以第一步,需要把new对象这一块的代码之间删掉,剩下部分如图:
如果现在直接运行controller中的方法就会报错,因为我们声明了empService变量,但是这个变量没有赋值,那么它的值就是null,在运行的时候就会报错:空指针异常。
第二步,提供一个容器,容器就是用来存东西的,在容器中,我们可以存储一些对象,假如我们现在想使用EmpserviceA这个实现类,我们只需要把这个类所创建出来的对象放在这个容器当中。如图:
接下来,controller程序在运行的时候,它需要依赖于EmpService,此时,我们可以到容器中去查找EmpService这个类型的对象,而A对象就是Empservie类型的,这时候,我们就可以从容器中找到这个对象,然后再将这个对象赋值给empService
接下来,程序运行的时候,empService就有值了,而这个对象就是从容器中拿到的。
这时候,如果我们要切换实现类,把实现类由EmpServiceA切换为EmpServiceB,这时我们可以基于EmpServiceB这个实现类创建对象放到容器当中,此时,controller在运行的时候,也需要一个EmpService类型的对象,而B对象就是这个类型,所以controller就通过容器拿到了B对象,再赋值给empService,然后就可以使用了。
此时我们发现,即使service层的实现类发生了变化,controller的代码也不需要改动,这样就完成了解耦。
四、控制反转和依赖注入-简述
要完成上述步骤,需要知道两个概念:控制反转和依赖注入。
- 控制反转:Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。理解:原来在应用程序中,我们需要什么对象,都是直接new对象,而现在是将所有的对象都交给了容器来管理,这就是控制反转,反转之前是由应用程序自身来控制对象的创建,反转之后,是由容器来控制,这个容器称为IOC容器或者Spring容器。
- 依赖注入:Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。比如controller程序在运行时,需要依赖empService这个资源,这时候可以让IOC容器来提供这个资源。该过程就称为依赖注入
- Bean对象:IOC容器中创建、管理的对象,称之为bean。