刚才我们学习过程序分层思想了,接下来呢,我们来学习下程序的解耦思想。
解耦:解除耦合。
3.2.1 耦合问题
首先需要了解软件开发涉及到的两个概念:内聚和耦合。
-
内聚:软件中各个功能模块内部的功能联系。
-
耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
软件设计原则:高内聚低耦合。
高内聚指的是:一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越高,则内聚性越高,即 "高内聚"。
低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。
程序中高内聚的体现:
-
EmpServiceA类中只编写了和员工相关的逻辑处理代码
程序中耦合代码的体现:
-
把业务类变为EmpServiceB时,需要修改controller层中的代码
高内聚、低耦合的目的是使程序模块的可重用性、移植性大大增强。
3.2.2 解耦思路
之前我们在编写代码时,需要什么对象,就直接new一个就可以了。 这种做法呢,层与层之间代码就耦合了,当service层的实现变了之后, 我们还需要修改controller层的代码。
那应该怎么解耦呢?
-
首先不能在EmpController中使用new对象。代码如下:
-
此时,就存在另一个问题了,不能new,就意味着没有业务层对象(程序运行就报错),怎么办呢?
-
我们的解决思路是:
-
提供一个容器,容器中存储一些对象(例:EmpService对象)
-
controller程序从容器中获取EmpService类型的对象
-
-
我们想要实现上述解耦操作,就涉及到Spring中的两个核心概念:
-
控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。
对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器
-
依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。
程序运行时需要某个资源,此时容器就为其提供这个资源。
例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入EmpService对象
IOC容器中创建、管理的对象,称之为:bean对象
自己的笔记
内聚:软件中各个功能模块内部的功能联系。
比如我们写的EmpServiceA类中只编写了和员工相关的逻辑处理代码,与员工无关我们并不会放在这个类中 这就是内聚程度比较高 也叫高内聚
耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
比如刚才我们编写的三层架构的程序中 Controller 去调用 Service 去调用 Dao
而Controller去调用 Service层的时候 要用到Service层的对象 所以我们要在Controlle层New一个Service层的实现类
private EmpService empService = new EmpServiceA();
一但 Controlle层New一个Service层的实现类之后 假如 Service层的实现类名发现变化
或者我们要切换一个实现类 那此时 Controlle层的代码就得修改
最起码new对象的部分得修改
所以这就是 Controlle层与Service层的代码耦合了
同样在Service层需要调用Dao 所以我们在Service层直接New一个Dao的实现类
private EmpDao empDao =new EmpDaoA();
这样Service层与Dao层之间也 耦合了
所以我们要解除耦合
这样各个层之间就不会互相影响
所以我们要提供容器进行存储对象(因为对象被我们给去掉了 所以我们得去容器中去拿到对象)
如果这个时候要切换实现类 由A实现类切换成B实现类
这个时候 我们就可以基于B实现类来创造一个对象放在容器当中
此时Controlle在运行的时候也要EmpService类型的对象
只需要从容器中去查找对象就可以
所以就算Service的代码发生变化 Controlle也不用去改动
这就是解耦
依赖注入(DI):容器为运用程序提供运行时所需要的资源
比如Controlle程序在运行时需要EmpService这个资源
那就让容器进行提供