IoC究竟shift什么?——IoC的基础分析

news/2025/1/12 17:43:37/文章来源:https://www.cnblogs.com/ENchantedN/p/18667122

IoC全称Inversion of Control,直译为控制反转。这是一种设计理念,并非技术。
在明白控制反转之前,应该知道“反转”反的是什么。

被反转的正转

我们从生活中的做饭场景开始。

在家做菜与餐馆吃饭

我们在做饭的时候有很多个步骤,需要准备原料,厨具等等。最后通过一定的顺序加入我们的原料,再进行翻炒等烹饪操作就能够得到一份菜了。
我们想吃一份菜不一定需要自己做,也可以去餐馆吃,只需要告诉餐馆我们要吃什么,餐馆就能自己做好给到我们手上吃

控制的正与反

在这个做饭的例子中,正转就是我们自己准备原料,自己通过烹饪方法做菜,而控制反转就是我们去的餐馆
这个时候我相信你还是不明白这俩有什么关系,为什么正转是自己做,而反转变成了餐馆的概念。没关系,我们继续深入。

什么是反转,反转在哪?

我们再回顾一遍,我们吃到菜是个什么流程。

  • 自己做饭:想好要做的菜——自己准备原料——自己烹饪——成品
  • 餐馆:想好要吃的菜——给餐馆说——餐馆烹饪——成品

我们自己设计一整套程序的时候,往往是有很多模块的,每个模块会相互协作使用,最终形成一个大的程序,我们需要自己一个一个将模块联系起来。这就是我们自己做菜的过程
而控制反转IoC就是将所有需要的模块通过一个容器(可以理解为一个控制终端)联系起来,我们不需要思考这个模块会不会使用其他的模块才能完成,全部都由容器帮我们完成联系。这就是我们去餐馆的过程,我们不用做菜,交给餐馆,而一个个原材料就是餐馆去准备的。
最终我们能看到反转的地方就在于,我们本来是靠自己去一个一个联系其模块来,但我们全都交给了容器,容器替我们完成了联系,我们反转了对自己的依赖,本来是依赖自己去联系的,现在变依赖容器,反转就在这。换句话说,控制反转应该叫控制反转

为什么要有IoC

这个时候你会说,这样不是省了很多事吗,省事不就是IoC的意义吗?
对了,但没完全对。换句话说,省事了,但没完全省。因为每个依赖还是要我们自己去配置的,只不过换了种方式(这个后面再说),IoC容器只是封装而已,但是这并不代表IoC没用,IoC最大的意义不在于它更方便,而是在于它能解耦

解耦在哪?

虽然容器只是帮我们完成了每个模块的依赖,但是我们前面说到,控制反转最大的意义就是我们只用把需要的功能给到容器,容器再去思考其他的,这样的话我们再写每个模块功能的时候就会更加独立,不用考虑依赖,每个模块变得更加独立那不就是解耦的初衷吗

实例

我们最后再来个实例看看效果
我们先创建一个接口

public interface Shape { void draw(); 
}

然后实现几个个接口

//Rectangle.java
public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}
//Square.java
public class Square implements Shape {@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}
//Circle.java
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

然后根据传入信息的不同,生成不同的对象

public class ShapeFactory {//use getShape method to get object of type shape public Shape getShape(String shapeType){if(shapeType == null){return null;}        if(shapeType.equalsIgnoreCase("CIRCLE")){return new Circle();} else if(shapeType.equalsIgnoreCase("RECTANGLE")){return new Rectangle();} else if(shapeType.equalsIgnoreCase("SQUARE")){return new Square();}return null;}
}

最后main方法调用,获取对象

public class FactoryPatternDemo {public static void main(String[] args) {ShapeFactory shapeFactory = new ShapeFactory();//get an object of Circle and call its draw method.Shape shape1 = shapeFactory.getShape("CIRCLE");//call draw method of Circleshape1.draw();//get an object of Rectangle and call its draw method.Shape shape2 = shapeFactory.getShape("RECTANGLE");//call draw method of Rectangleshape2.draw();//get an object of Square and call its draw method.Shape shape3 = shapeFactory.getShape("SQUARE");//call draw method of circleshape3.draw();}
}

这就是工厂模式,工厂实现的方式原理是根据传入的某个参数获取一个对象,一旦我们新增一个shape类型,就修改ShapeFactory 类。这种方式不够灵活,并违背了软件设计的开闭原则。

开闭原则:一个软件实体, 如类, 模块, 函数等应该对扩展开放, 对修改封闭.
对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对已有代码进行任何修改。

要想做到不修改的动态查看类的类型,反射就是一个不错的选择。

Java 反射(Reflection)是一个强大的特性,它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。

那么思路就有了,最后的修改就是这样:

public class ShapeFactory {private ShapeFactory(){}public static Shape getInstance(String className){Shape shape = null;try {shape = (Shape) Class.forName(className).newInstance();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}return shape;}
}

而利用反射的代码就封装到了Class.forName里面

@CallerSensitive
public static Class<?> forName(String className)throws ClassNotFoundException {Class<?> caller = Reflection.getCallerClass();return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

IOC底层原理主要用到了3种技术:工厂模式、反射、XML解析
XML文件的配置这里我们不多说,下一章我们具体来说如何做,这里就明白我们的依赖管理都是类似于maven中的pom.xml一样管理的就行。

工厂模式、反射、XML解析的结合完成了IoC的所有技术概括,形成了巧妙的化学反应,我们后面spring都是基于整个概念在前行。

这可能是最好的Spring教程!

感谢您看到这里 这可能是最好的Spring教程系列 更多的文章可以到这查看这可能是最好的Spring教程!即便无基础也能看懂的入门Spring,仍在持续更新。,我还在荔枝更新出最详细的Spring教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/868271.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸟哥的Linux私房菜 基础学习篇 第四版PDF、EPUB免费下载

Linux入门书升级版,适用Linux系统应用和开发及运维的人员,涵盖linux内核,命令行,嵌入式,基于CentOS,7.x适读人群 :Linux初学者 适合Linux管理员作为参考手册 Linux入门书升级版,适用Linux系统应用和开发及运维的人员,涵盖linux内核,命令行,嵌入式,基于CentOS,7.x电…

领域驱动设计:软件核心复杂性应对之道(修订版)PDF、EPUB免费下载

本书是领域驱动设计方面的经典之作,修订版更是对之前出版的中文版进行了全面的修订和完善。全书围绕着设计和开发实践,结合若干真实的项目案例,向读者阐述如何在真实的软件开发中应用领域驱动设计。书中给出了领域驱动设计的系统化方法,并将人们普遍接受的一些实践综合到一…

JAVA之集合

1、集合集合可以存储引用数据类型; 集合不可以存储基本数据类型,若要存储,需封装成包装类;2、集合和数组的对比长度【数组长度固定,集合长度可变】 存储类型【数组可以存基本数据类型和引用数据类型,集合可以存引用数据类型,若存储基本数据类型,需封装成包装类】3、Arr…

[题目记录]P9999 [Ynoi2000] tmostnrq

当前自己写过了码量第二大的题目 , 不管怎么说对拍非常重要 .P9999 [Ynoi2000] tmostnrq 题意 给定 \(n\) 个顶点的树,顶点编号为 \(1,\dots,n\),给定长度 \(n_0\) 的序列 \(a_1,\dots,a_{n_0}\),共 \(m\) 次查询,每次查询给定 \(l,r,x\),问树的顶点 \(x\),依次向 \(a_l,…

多光谱火焰智能监测摄像机

多光谱火焰智能监测摄像机将在未来继续发展。未来的摄像机可能会更加智能化,具备更强的自主识别和决策能力,进一步提升火灾监测的灵敏度和准确性。此外,随着物联网的发展,这些摄像机还有望与其他设备和系统实现更深入的数据共享和集成应用,为整个安全监控体系增添新的可能…

明火智能监测摄像机

明火智能监测摄像机检测到火源时,它会立即触发报警机制,以警告人员采取适当的行动。它可以与各种报警系统集成,发出清晰可闻的警报声,并通过网络将警报信息发送到相关部门或人员的手机应用程序,确保快速响应。明火智能监测摄像机全天候工作,不间断地监测环境中的火情。它…

山体滑坡自动监测识别摄像机

山体滑坡自动监测识别摄像机系统通过技术创新和智能化应用,为减少自然灾害带来的损失和风险提供了重要的技术手段和支持。随着技术的进步和系统的完善,相信这类系统将在全球范围内得到广泛应用,为社会公共安全和环境保护作出更大贡献。对于现代社会而言,山体滑坡作为自然灾…

水位智能监测识别摄像机

水位智能监测识别摄像机的应用前景十分广阔。未来,这些摄像机有望进一步提升监测精度和反应速度,扩展到更多复杂的水域环境和特殊应用场景中,为保障社会公共安全和生态环境做出更大贡献。总之,水位智能监测识别摄像机以其先进的技术和多功能性能,正在成为水域监测领域的重…

1.12 CW 模拟赛 T1. 括号序列

思路 根据赛时的检验, 典型的动点问题的 \(\rm{trick}\) 并不能在这里使用, 也就是说, 分类讨论前缀 + \(i\) + 后缀 前缀 + \(i\) 后缀 + \(i\)是不可行的 考虑括号串问题的常见做法, 先将其赋值成 \(1, -1\) 之后进行处理 你发现这种做法有枚举字段和的瓶颈, 所以也不可行 当…

【Docker】Docker搭建一款开源的RAG聊天应用

项目介绍 Kotaemon是一个由Cinnamon开发的开源项目,旨在提供一个基于检索增强生成(RAG)技术的用户界面,使用户能够与自己的文档进行交互问答。 功能特点 文档问答:Kotaemon允许用户通过自然语言查询与文档进行交互,快速获取所需信息。这一功能在学术研究、企业文档管理等…

客梯自动监测识别摄像机

客梯自动监测识别摄像机通过技术创新和智能化应用,为现代城市客梯的安全管理提供了全新的解决方案。随着技术的不断进步和应用场景的扩展,相信这类系统将在全球范围内得到广泛应用,为乘客的安全出行和客梯运行的高效管理提供更加可靠的保障和支持。当今社会,随着城市建设的…

【Docker】Docker搭建一款开源的加密货币量化交易平台

项目介绍 Freqtrade是一个开源的加密货币量化交易平台,它允许用户通过编写和配置交易策略来自动化交易过程。 功能特点 开源性:Freqtrade的代码是开源的,这意味着用户可以查看、修改和扩展平台的功能。 自动化交易:通过配置交易策略,Freqtrade可以自动执行买卖操作,无需人…