浅谈控制反转(IoC)

2023-10-29

Inversion of Control

什么是控制反转?

程序的流程控制权相对于传统的面向过程编程而言发生了反转。下面是维基百科的描述

In software engineering, inversion of control (IoC) is a programming principle. IoC inverts the flow of control as compared to traditional control flow.

看到这里大家可能会觉得云里雾里的…控制反转(Inversion of Control)实际是控制(Control)和反转(Inversion)两个词的组合,所以拨开云雾的关键在于理解控制反转

怎么理解“控制”?

程序的流程控制权,决定程序的运行方式和流程。

举个例子,想必大家都知道,要把大象放进冰箱需要三步:1)打开冰箱门;2)把大象放进冰箱;3)关上冰箱门。用一段代码用表示的话,代码可能长这样

void putElephantToRefrigerator() {
    打开冰箱门;
    放进大象;
    关闭冰箱门;
}

int main() {
    putElephantToRefrigerator();
    return 0;
}

不过,冰箱可能已经被塞满放不下大象了,我们需要把冰箱里没用的东西清理掉,再把大象团成团放进去,代码会变成这样

void putElephantToRefrigerator() {
    打开冰箱门;
    清理冰箱;
    把大象团成团;
    放进大象;
    关闭冰箱门;
}
...

当然,我们完全可以先把大象团成团,像这样

void putElephantToRefrigerator() {
    把大象团成团;
    打开冰箱门;
    清理冰箱;
    放进大象;
    关闭冰箱门;
}
...

所以,我们要把大象放进冰箱里都会经过一个流程,目前这个流程是由我们自己控制的。

怎么理解“反转”?

相对于传统的面向过程编程实践而言

  • 程序的流程控制权发生了转变
  • 应用程序与第三方代码之间的调用关系发生了转变

继续看上面的例子,假如我们有一款极其智能的冰箱,不需要手动开门、关门,只要关心放什么东西进去、怎么放进去(nice,事情变得更简单了),代码会变成这样(考虑设计模式-模板方法)

typedef struct AutoRefrigerator;

struct MyRefrigerator : AutoRefrigerator {
    private void putSomething() {
        ...
    }
}

int main() {
    MyRefrigerator refrigerator;
    refrigerator.put(elephant);
    return 0;
}

代码中“refrigerator.put(elephant);”由框架提供,包含多条子语句(open、close、putSomething…),但putSomething没具体实现,需要我们自己定制。

此时,控制程序流程的不是我们的代码而是框架提供的AutoRefrigerator,程序流程控制权发生了反转,控制权由我们自己的代码转移到了框架中

控制反转前后有哪些变化呢?

  • 反转前:我们自己的代码决定程序的工作流程,并调用第三方代码(我们自己的代码是甲方,第三方代码是乙方)
  • 反转后:第三方代码(框架)决定程序的工作流程,并调用我们写的代码(我们自己的代码是乙方,第三方代码是甲方)

可见,在控制反转前我们写的代码会调用第三方代码,而控制反转后则是由第三方代码(框架)调用我们的代码,这种代码调用关系的反转也是控制反转的意义

有什么好处?

好处?怎么可以这么物质?这个问题超纲了,暂且不谈…笔者是个物质的人,所以只谈谈有什么好处。

好处用两个字概括:复用用Paul Graham的话来说,复用就是软件圣杯)。

复用代码有三种方式:类库、框架、设计模式。

  • 类库强调代码复用
    定义一组可复用的代码,供其他程序调用——拿来主义,别人的东西拿来用,用别人的锤子砸核桃。
  • 框架强调设计复用
    定义程序的体系结构,开发人员通过预留的接口插入代码(做填空题)——把自己的锤子装在流水线上,让它砸核桃。
  • 设计模式复用解决方案
    设计模式提供了解决一类问题的有效经验,复用这些经验往往可以很好地解决问题——看别人是怎么砸核桃的,依葫芦画瓢模仿一遍。

控制反转为复用框架提供了可能性。框架定义了解决一类问题的流程、体系结构,但程序的特定细节需要定制,因此框架需要调用我们写的代码,控制反转提供了这种可能性。控制反转和编码原则之一的好莱坞原则(It calls me rather me calling the framework) 也存在着紧密的联系。

另外,按照Martin Fowler的描述,控制反转还有Seperating Configuration from Use的作用。实际上这是一些容器的主要作用(如Spring),而这些容器又不可避免地使用了控制反转。

怎么实践?

说了这么多,又有这么诱人的好处,怎么才能得到它呢?

最简单的实践就是设计模式-模板方法,不过最常见的实践方法还是依赖注入依赖查询
依赖注入(DI:Dependency Inject):被动接收依赖对象,由容器将被依赖对象注入到对象内部;
依赖查询(DL:Dependency Lookup):主动查询依赖对象,由对象自身通过 服务定位器 查询被依赖对象;依赖查询也经常以服务定位器模式(Service Locator)的形式出现。

DI DL
在这里插入图片描述 在这里插入图片描述
Context依赖各事例 各实例依赖context
通过构造函数、setter函数等容易查看依赖关系 依赖关系不容易查看,需要分析调用locator的源码分析依赖关系
装配关系在业务类外的配置文件中 装配关系在业务类中
被动接收依赖对象 主动查询依赖对象

这两种方式的主要区别在于配置方式不同、获得依赖对象的方式不同。

该怎么决定在代码中使用DI还是DL呢?Martin Fowler有话说

So the decision between locator and injector depends on whether that dependency is a problem.

参考连接

https://www.martinfowler.com/bliki/InversionOfControl.html
https://www.martinfowler.com/articles/injection.html
https://en.wikipedia.org/wiki/Inversion_of_control

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈控制反转(IoC) 的相关文章

随机推荐

  • TASK9 Boosting

    Boosting PAC学习 概率近似正确学习 PAC总结理论 同等条件下 模型越复杂泛化误差越大 同一模型在样本满足一定条件的情况下 其数量越大 模型泛化误差越小 因此还可以说模型越复杂越吃样本 某个训练样本对正确目标的映射 而称为 概念
  • Microsoft Dynamics CRM 2013 试用之系统篇 正式安装 Microsoft Dynamics CRM Server 2013

    想学习Microsoft Dynamics CRM 建议从本人博客CRM中从早到晚日期 完整看一遍 然后再安装 安装需要的文件直接到微软官方下载 1 下载 Microsoft Dynamics CRM Server 2013 2 运行 Se
  • 深度学习语音降噪总结

    实时语音通信发展到今天 用户对通话语音质量提出了越来越高的要求 由于终端设备的多样性以及使用场景的差异 声音问题依然存在 传统的音频处理技术从声音信号本身出发 挖掘其时频特性 作出假设 建立物理模型 很多参数都需要人工进行精细化微调 比较费
  • can only concatenate list (not "str") to list 解决

    我的代码 info item title n item content n 写python代码出现这个提示的时候 can only concatenate list not str to list 该提示字面意思是 只能将list类型和li
  • ubuntu 相关命令记录

    检查ssh 是否可用 ssh 安装curl apt install curl 进入root 进入root 账号 sudo i 修改密码 sodo passwd 开启root 可远程连接 修改SSH配置文件 可以通过SSH配置文件更改包括端口
  • git clone出错问题解决

    一 git clone 报错 错误截图如下 原因分析 可能是数据太大了 http协议不支持 二 改用ssh方式检出代码 第一步 Git Bash工具生成ssh key ssh keygen o t rsa C your email exam
  • 江河湖库水系连通及水美乡村监测系统解决方案

    一 方案背景 随着我国城市规模化的扩张 城市水系统面积萎缩 水生态系统衰退 水环境质量恶化 河道淤塞甚至被侵占为建筑用地等问题日益凸显 河湖水系连通在城市河道治理中占据举足轻重的位置 水系连通及水美乡村建设项目 是水利部 财政部为解决农村水
  • JavaScript 算法系列---动态规划

    很久之前接触过这样一道题目 总共有十层阶梯 从1层开始往上爬 每次可以上1层或者2层 问到10层总共有多少种方法 思路 这个问题就是动态规划的一个经典例子 所谓动态规划 就是把复杂的问题进行拆解 拆解成一个个子问题 而这类问题最后非常适合使
  • C++ 学习之内建函数对象 - 算术仿函数(加减乘除、取反、取余)

    算数仿函数原型 template
  • 自定义图标iconfont

    阿里iconfont的使用 ui切好图上传到蓝狐 我们下载svg格式的图片 登陆iconfont官网 然后将自己取的iconfont的昵称也就是用户名给你们负责人说 叫他把你拉入图标管理库 这样才能共同开发 全部人各自定义自己的图标 不冲突
  • MySQL实操(四)——使用Haproxy+keeplived实现Mycat高可用

    MySQL实操系列 MySQL实操 一 CentOS7安装MySQL5 7及基础配置 DreamEhome的博客 CSDN博客 centos7 中安装mysql5 7配置表名忽略大小写 MySQL实操 二 MySQL主从同步实战 Dream
  • Labview操作串口-----------通过VISA驱动

    本篇文章将会详细介绍如何通过labview的VISA驱动模块来操作PC的串口 基于LABVIEW2012 VISA530full exe 1 首先需要安装LABVIEW 接下里安装VISA530驱动模块 否则编译本代码时会出现缺少VISA驱
  • STM32 四轴无人机设计——PPM控制无人机动作

    1 前言 前面两次我们成功的将PPM信号的读取 储存和油门处理完成了 这次我们要开始真正的控制无人机 首先我们要了解无人机前后 左右 旋转 升降的原理 2 动作原理 引用 https blog csdn net weixin 3570379
  • flutter get 命令行工具

    mac终端执行 flutter pub global activate get cli 这个安装完以后会提示英文提示你要把一个 目录添加到mac环境变量中 下面的目录是你安装完以后提示你放到环境变量里的目录 export PATH PATH
  • [MacOs]用外置硬盘制作MacOs系统盘

    文章目录 背景 设备 步骤 下载指定系统 制作启动盘 安装系统 背景 最近我的mac air出了点问题 经检查应该是硬盘问题 由于最近得待在老家没办法维修又需要用 只能用外置的硬盘做个系统盘来将就一下使用 设备 需要两个存储设备 不小于32
  • 马上:头疼:安卓黑屏,白屏,网卡,sdcard挂载等问题深入分析解决

    白屏 设备一段时间使用后 白屏 需要重启 经线上日志和以下相关代码初步分析是AMS 窗口显示问题 检查相关业务代码 发现Activity有可能被finish多次 导致失败 还有多次startActivity if isFinishing r
  • MySQL数据库误删回滚

    某次一不小心 用了delete from xxx 删除了几条重要数据 在网上找了很多方法 但都比较零散 打算记录本次数据找回的过程 大致分为以下几步 1 查看binlog是否开启 log bin是ON 就说明打开了 OFF就是关闭状态 以下
  • linux查看nginx安装路径

    linux查看nginx安装路径 有几种方法可以查看nginx的安装路径 使用which命令 which nginx 这个命令会返回nginx的二进制文件路径 一般也是安装路径 查看nginx的进程 得到安装路径 ps aux grep n
  • python爬虫高级教程,JS逆向之百度翻译

    环境 python版本号 系统 游览器 python 3 7 2 win7 google chrome 关于本文 本文将会通过爬虫的方式实现简单的百度翻译 本文中的代码只供学习 不允许作为于商务作用 商务作用请前往api fanyi bai
  • 浅谈控制反转(IoC)

    Inversion of Control 什么是控制反转 程序的流程控制权相对于传统的面向过程编程而言发生了反转 下面是维基百科的描述 In software engineering inversion of control IoC is