本篇和大家一起学习IoC和DI即控制反转和依赖注入。

当然听上去这词语非常的专业,真不知道是怎么组出来的,看上去难归看上去难,但稍微理解一下也就这么回事了。

首先我们要明白IoC/DI干嘛用的,不然别人问“你知道IoC/DI吗?”,“知道啊!”,“那干嘛用的?”,呵呵,就郁闷了,其实IoC/DI的作用就两个字——解耦,说一千道一万,还是离不开这两个字。所以,IoC/DI的作用就是解耦。

至于为什么要解耦,解耦在面向对象开发中的重要性在这里就不做细说了。

下面我们来认识一下它们的真面目吧!

要理解IoC/DI两个概念,就必须搞清楚如下问题:

  • 参与者都有谁?
  • 依赖:谁依赖于谁?为什么需要依赖?
  • 注入:谁注入谁?到底注入了什么?
  • 控制反转:谁控制谁?控制什么?为什么叫反转?有没有正向呢?正向又是什么?
  • 依赖注入和控制反转是同一概念吗?

下面来简要回答一下上述问题,把这些问题搞明白了,也就明白了IoC/DI。

  1. 参与者都有谁:一般有三方参与,一个是某个对象,一个是IoC/DI容器,还有就是某个对象的外部资源。

    注:某个对象指任意一个普通的对象,IoC/DI容器简单说就是用来实现IoC/DI功能的一个框架程序,比如现在有许多IoC/DI框架(Unity、Spring.NET、Autofac),对象的外部资源指对象需要的,但是从对象外部获取的,都统称资源,比如对象需要其他对象。

  1. 谁依赖于谁:当然是某个对象依赖于IoC/DI容器
  2. 为什么需要依赖:因为对象需要IoC/DI的容器来提供对象需要的外部资源。
  3. 谁注入谁:IoC/DI的容器注入某个对象
  4. 到底注入了什么:就是注入某个对象所需要的外部资源,说完整点就是IoC/DI的容器将某个对象所需要的外部资源注入了该对象。
  5. 谁控制谁:IoC/DI的容器来控制对象
  6. 控制什么:主要是控制对象实例的创建
  7. 为什么叫反转:反转是相对与正向而言的。
  8. 正向又是什么:通常情况下的应用程序,如果在A里使用C,一般我们会直接创建C的对象,也就是说,在A类中主动获取所需要的外部资源,这种情况被成为正向的,那什么是反向呢?就是A类不再主动去获取C,而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向地注入到A类中。

先看没有IoC/DI的时候,常规A类使用C的示意图

当有了IoC/DI的容器后,A类不再主动去创建C了,而是被动等待,等待IoC/DI的容器获取C的实例,然后反向注入到A类中。

依赖注入和控制反转是同一概念吗?

根据上面讲述,依赖注入和控制反转是对同一件事情的不同描述。依赖注入使用应用程序的角度去描述,我们可以把依赖注入描述的完整点:应用程序依赖容器创建并注入它所需要的外部资源。控制反转是从容器的角度去描述的,描述的完整点就是:容器控制应用程序,由容器反向的向应用程序注入其所需要的外部资源。

好了,通过上述学习,大家都应该对IoC/DI有了基本了解,下面我们再来正式认识下依赖注入和控制反转。

依赖注入中,依赖关系就像被注入的液体,我们可以在任何时候将依赖关系注入到模块中,而不只局限于编译是绑定。这种依赖关系是通过注入的方式完成的,就意味着我们可以随时更新,因为注入的液体与模块本身并无直接关联,举个不恰当的比喻,我们难道天生就要和针筒打交道吗?

实现依赖注入的前提是面向接口编程,辅助的技术可以使用反射技术。

MF.将依赖注入的形式分为三种:构造函数注入、设置方法注入和接口注入。

接口注入是通过定义接口约束的方式实现依赖注入,会给容器带来设计的限制。

而构造函数注入与设置方法(可以是属性)注入则是使用类的构造函数以及自定义的setter方法或属性进行依赖注入(关于这两点,可以参考第一篇《设计模式之UML类图的常见关系(一)》中的聚合和组合关系)。

在这里我们也把第一篇聚合和组合关系类图拿到了。

下面这个是使用Setter方法/属性实现依赖注入的。说白了就是定义一个Setter方法/属性,在该方法/属性内将对象关联起来。

下面这个是构造函数的依赖注入,就是将Setter方法/属性换成了构造函数,但是请仔细看看两幅图片的代码和注入,什么时候使用Setter方法/属性注入,什么时候使用构造函数注入,当时在开发过程中,通常是使用构造函数进行依赖注入的。

还有一个就是接口注入。

这是我认为最不够优雅的一种依赖注入方式。要实现接口注入,首先ServiceProvider要给出一个接口定义:

public interface InjectFinder {
void injectFinder(MovieFinder finder);
}

接下来,ServiceUser必须实现这个接口:

class MovieLister: InjectFinder
{
private MovieFinder finder;
public void injectFinder(MovieFinder finder) {
this.finder = finder;
}
}

为什么现在介绍IoC/DI呢?

想想,前面我们已经学习了三种工厂,那能不能将工厂和IoC/DI联系起来呢?好了,下面就自己想想!

小结:IoC/DI对编程带来的最大改变不是在代码上,而是在思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动了,被动的等待IoC/DI容器来创建并注入它所需要的资源。

设计模式之初识IoC/DI(六)的更多相关文章

  1. 设计模式——从工厂方法模式到 IOC/DI思想

    回顾简单工厂 回顾:从接口的角度去理解简单工厂模式 前面说到了简单工厂的本质是选择实现,说白了是由一个专门的类去负责生产我们所需要的对象,从而将对象的创建从代码中剥离出来,实现松耦合.我们来看一个例子 ...

  2. PHP程序员如何理解IoC/DI(转)

    php - Dependency Injection依赖注入 和 自动加载 各自的优缺点 ioc/di和自动加载时两回事. ioc/di 让代码由创建对象改为注入对象,是一种编程思想,而自动加载,只是 ...

  3. 关于依赖注入IOC/DI的感想

    之前一直不明白依赖注入有什么好处,甚至觉得它是鸡肋,现在想想,当时真是可笑. 这个想法正如同说接口是没有用处一样. 当整个项目非常庞大,各个方法之间的调用非常复杂,那么,可以想象一下,假设说没有任何的 ...

  4. 如何理解IoC/DI

    IoC:Inversion of Control,控制反转DI:Dependency Injection,依赖注入 要理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁?依赖:谁依赖于谁?为什么 ...

  5. IOC DI 专题

    IoC:Inversion of Control,控制反转DI:Dependency Injection,依赖注入 要理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁?依赖:谁依赖于谁?为什么 ...

  6. Spring4学习回顾之路02—IOC&DI

    IOC&DI介绍 ●IOC:(Inversion of Control) :控制反转(反向获取资源) 其思想是反转资源获取的方向.传统的资源上查找方式要求组件向容器发起请求查找资源,作为回应, ...

  7. Spring框架——IOC&DI

    Spring Spring 目标 内容 Spring与web整合的原理 Spring 中包含的关键特性 Spring架构图 企业级框架 企业级系统 IOCDI IOC DI IOC和DI 为什么使用依 ...

  8. Spring IOC/DI和AOP原理

    一 IOC/DI 1. 概念机原理 IOC: Inversion of Control(控制反转)是一种设计思想,就是容器控制应用程序所需要外部资源的创建和管理,然后将其反转给应用程序.对象及其依赖对 ...

  9. 深入理解IoC/DI

    ------------------------------------------------------------------------ 理解IoC/DI 1.控制反转 --> 谁控制谁 ...

随机推荐

  1. composer概念学习

    composer的中文文档地址 Composer是什么 Composer 是 PHP 的一个依赖管理工具.它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们. Composer 不是一个包管 ...

  2. Sahi (1) —— 快速入门(101 Tutorial)

    Sahi (1) -- 快速入门(101 Tutorial) jvm版本: 1.8.0_65 sahi版本: Sahi Pro 6.1.0 参考来源: Sahi官网 Sahi Quick Tutori ...

  3. docker:Error running DeviceCreate (createSnapDevice) dm_task_run failed

    1) service docker stop 2) thin_check /home/docker/devicemapper/devicemapper/metadata 3) thin_check - ...

  4. Scrapy 导出的 cvs 文件,双击打开乱码问题

    默认可能是utf8格式,在excel的不要直接打开,而是在excel - 数据 -导入里打开,或者打开前用vscode之类的保存为GBK编码

  5. kinect2的标定

    我用的是ubuntu14.04LTS,ROS 版本是indigo,kinect v2,我是用双系统装的ubuntu,关于怎么使用安装kinect2的安装以及使用的都在github上有着详细的说明 Ki ...

  6. js学习(四)- prototype原型对象

    前言: 下面两行代码都是创建一个数组对象myArray:var myArray=[];//等价于var myArray=new Array();同样,下面的两段代码也都是创建一个函数myFunctio ...

  7. 基于html5 canvas 的客户端异步上传图片的插件,支持客户端压缩图片尺寸

    /** * Created by xx on 15-05-28. * 基于html5 canvas 的客户端异步上传画片的插件 * 在实际应用中,常常要用于上传图片的功能.在现在越来越多的手机weba ...

  8. JFinal的使用

    JFinal 中的Controller Controller是JFinal核心类之一,该类作为MVC模式中的控制器.基于JFinal的Web应用的控制器需要继承该类.Controller是定义Acti ...

  9. 14款优秀的JavaScript调试工具大盘点

    JavaScript是一种非常简单的语言,一般说来任何人都可以在几小时内掌握它的基本知识. 然而就像其他任何语言一样,JavaScript存在着一些可以轻易避免的常见错误和不好的做法.开发人员喜欢使用 ...

  10. paoding分词

    Paoding 详细介绍 庖丁中文分词库是一个使用Java开发的,可结合到Lucene应用中的,为互联网.企业内部网使用的中文搜索引擎分词组件.Paoding填补了国内中文分词方面开源组件的空白,致力 ...