Spring - IOC
知识点-工厂模式解耦
1.目标
能够使用工厂模式进行解耦
2.路径
程序耦合的概述
使用工厂模式解耦
3.讲解
3.1 程序的耦合
3.1.1 程序耦合的概述
耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。 耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。
在软件工程中, 耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计
应使类和构件之间的耦合最小。 软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。 划分模块的一个
准则就是高内聚低耦合。
总结:
耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。内聚与耦合内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。耦合是软件
结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。 程序讲究的是低耦合,高内聚。就是同一个模块内的各个元素之间要高度紧密,但是各个模块之
间的相互依存度却要不那么紧密。
内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其他
模块之间是低耦合。在进行软件设计时,应力争做到高内聚,低耦合。
3.1.2 在代码中体现
早期我们的 JDBC 操作(面向接口的编程),注册驱动时,我们为什么不使用 DriverManager 的 register 方法,而是采
用 Class.forName 的方式?
原因就是: 我们的类依赖了数据库的具体驱动类(MySQL) ,如果这时候更换了数据库(比如 Oracle) ,
需要修改源码来重新数据库驱动。这显然不是我们想要的。
第一种耦合:一个类直接依赖另外一个类
第二种耦合:将字符串直接写死在 Java 代码中(字符串的硬编码)
3.1.3 解决程序耦合的思路
产生类与类之间的耦合的根本原因是:在一个类中 new 了另外一个类的对象
解决耦合的思路:不在类中创建另外一个类的对象,但是我们还需要另一个类的对象;由别人(Spring)把那个类的对象创建好之后给我用就可以了
当是我们讲解 jdbc 时,是通过反射来注册驱动的,代码如下:
Class.forName("com.mysql.jdbc.Driver");//此处只是一个字符串
此时的好处是,我们的类中不再依赖具体的驱动类,此时就算删除 mysql 的驱动 jar 包,依然可以编译(运行就不要想了没有驱动不可能运行成功的) 。
同时,也产生了一个新的问题, mysql 驱动的全限定类名字符串是在 java 类中写死的,一旦要改还是要修改源码。解决这个问题也很简单,使用配置文件配置
3.2.自定义 IOC(工厂模式解耦)
原始方式
+ 方式: 创建类, 直接根据类 new 对象
+ 优点: 好写, 简单
+ 缺点: 耦合度太高, 不好维护
接口方式
+ 方式: 定义接口, 创建实现类. 接口=子类的对象
+ 优点: 耦合度相对原始方式 减低了一点
+ 缺点: 多写了接口, 还是需要改源码 不好维护
自定义 IOC
+ 方式: 使用对象的话, 不直接 new()了,直接从工厂里面取; 不需要改变源码
3.2.1 原始方式
代码略
3.2.2 接口方式
UserService.java
UserServiceImpl.java
TestSpring.java
3.2.3 自定义 IOC(使用工厂模式解耦)
3.2.2.1 工厂模式解耦思路
在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候, 让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件, 创建和获取三层对象的类就是工厂
3.2.2.2 实现
添加坐标依赖
UserService.java
UserServiceImpl.java
Client.java
BeanFactory.java
下面的通过 BeanFactory 中 getBean 方法获取对象就解决了我们代码中对具体实现类的依赖。
spring.xml
4.小结
程序初始化的时候, 解析 xml, 全部解析好 存到容器【Map】里面
把 bean 标签的 id 作为 map 的 key, bean 标签的 class 属性值反射创建对象之后作为 map 的 value
要使用对象, 不再直接 new 了, 而是从容器里面直接取
知识点-IOC 概念
1.目标
[ ] 能够理解 IOC 概念
2.路径
分析和 IOC 的引入
IOC 概述
3.讲解
3.1 分析和 IOC 的引入
上一小节我们通过使用工厂模式,实现了解耦。
它的核心思想就是:
1、通过 Bean 工厂读取配置文件使用反射创建对象。
2、把创建出来的对象都存起来,当使用者需要对象的时候,不再自己创建对象,而是调用 Bean 工厂的方法从容器中获取对象
这里面要解释两个问题:
第一个:存哪去?
分析:由于我们是很多对象,肯定要找个集合来存。这时候有 Map 和 List 供选择。
到底选 Map 还是 List 就看我们有没有查找需求。有查找需求,选 Map。
所以我们的答案就是:在应用加载时,创建一个 Map,用于存放三层对象。我们把这个 map 称之为容器。
第二个: 什么是工厂?
工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。
原来:我们在获取对象时,都是采用 new 的方式。 是主动的。
3.2IOC 概述
IOC(inversion of control)的中文解释是“控制反转”,对象的使用者不是创建者. 作用是将对象的创建 反转给 spring 框架来创建和管理。
控制反转怎么去理解呢。 其实它反转的是什么呢,是对象的创建工作。 举个例子:平常我们在 servlet 或者 service 里面创建对象,都是使用 new 的方式来直接创建对象,现在有了 spring 之后,我们就再也不 new 对象了,而是把对象创建的工作交给 spring 容器去维护。我们只需要问 spring 容器要对象即可
ioc 的作用:削减计算机程序的耦合(解除我们代码中的依赖关系)。
4.小结
IOC: 控制反转. 对象的使用者不是创建者. 把对象的创建和管理, 交给 Spring 框架. 要使用的时候, 直接从 Spring 工厂(容器)里面取
作用: 解耦.
版权声明: 本文为 InfoQ 作者【小马哥】的原创文章。
原文链接:【http://xie.infoq.cn/article/80fdf36a94124a1943ba632ad】。文章转载请联系作者。
评论