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

金歌  金牌会员 | 2025-1-12 15:48:15 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 918|帖子 918|积分 2754

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

我们从生活中的做饭场景开始。
在家做菜与餐馆吃饭

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

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

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

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

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

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

我们最后再来个实例看看效果
我们先创建一个接口
  1. public interface Shape {
  2.         void draw();
  3. }
复制代码
然后实现几个个接口
  1. //Rectangle.java
  2. public class Rectangle implements Shape {
  3.    @Override
  4.    public void draw() {
  5.       System.out.println("Inside Rectangle::draw() method.");
  6.    }
  7. }
复制代码
  1. //Square.java
  2. public class Square implements Shape {
  3.    @Override
  4.    public void draw() {
  5.       System.out.println("Inside Square::draw() method.");
  6.    }
  7. }
复制代码
  1. //Circle.java
  2. public class Circle implements Shape {
  3.    @Override
  4.    public void draw() {
  5.       System.out.println("Inside Circle::draw() method.");
  6.    }
  7. }
复制代码
然后根据传入信息的不同,生成不同的对象
  1. public class ShapeFactory {
  2.    //use getShape method to get object of type shape
  3.    public Shape getShape(String shapeType){
  4.       if(shapeType == null){
  5.          return null;
  6.       }        
  7.       if(shapeType.equalsIgnoreCase("CIRCLE")){
  8.          return new Circle();
  9.       } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
  10.          return new Rectangle();
  11.       } else if(shapeType.equalsIgnoreCase("SQUARE")){
  12.          return new Square();
  13.       }
  14.       return null;
  15.    }
  16. }
复制代码
最后main方法调用,获取对象
  1. public class FactoryPatternDemo {
  2.    public static void main(String[] args) {
  3.       ShapeFactory shapeFactory = new ShapeFactory();
  4.       //get an object of Circle and call its draw method.
  5.       Shape shape1 = shapeFactory.getShape("CIRCLE");
  6.       //call draw method of Circle
  7.       shape1.draw();
  8.       //get an object of Rectangle and call its draw method.
  9.       Shape shape2 = shapeFactory.getShape("RECTANGLE");
  10.       //call draw method of Rectangle
  11.       shape2.draw();
  12.       //get an object of Square and call its draw method.
  13.       Shape shape3 = shapeFactory.getShape("SQUARE");
  14.       //call draw method of circle
  15.       shape3.draw();
  16.    }
  17. }
复制代码
这就是工厂模式,工厂实现的方式原理是根据传入的某个参数获取一个对象,一旦我们新增一个shape类型,就修改ShapeFactory 类。这种方式不够灵活,并违背了软件计划的开闭原则。
开闭原则:一个软件实体, 如类, 模块, 函数等应该对扩睁开放, 对修改封闭.
对扩睁开放,意味着有新的需求或变化时,可以对现有代码举行扩展,以适应新的情况。
对修改封闭,意味着类一旦计划完成,就可以独立完成其工作,而不要对已有代码举行任何修改。
要想做到不修改的动态查看类的类型,反射就是一个不错的选择。
Java 反射(Reflection)是一个强大的特性,它答应程序在运行时查询、访问和修改类、接口、字段和方法的信息。
那么思路就有了,最后的修改就是如许:
  1. public class ShapeFactory {
  2.     private ShapeFactory(){}
  3.     public static Shape getInstance(String className){
  4.         Shape shape = null;
  5.         try {
  6.             shape = (Shape) Class.forName(className).newInstance();
  7.         } catch (ClassNotFoundException e) {
  8.             e.printStackTrace();
  9.         } catch (IllegalAccessException e) {
  10.             e.printStackTrace();
  11.         } catch (InstantiationException e) {
  12.             e.printStackTrace();
  13.         }
  14.         return shape;
  15.     }
  16. }
复制代码
而使用反射的代码就封装到了Class.forName内里
  1. @CallerSensitive
  2. public static Class<?> forName(String className)
  3.                 throws ClassNotFoundException {
  4.      Class<?> caller = Reflection.getCallerClass();
  5.      return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
  6. }
复制代码
IOC底层原理主要用到了3种技能:工厂模式、反射、XML解析
XML文件的设置这里我们不多说,下一章我们具体来说如何做,这里就明确我们的依赖管理都是类似于maven中的pom.xml一样管理的就行。
工厂模式、反射、XML解析的结合完成了IoC的所有技能概括,形成了巧妙的化学反应,我们后面spring都是基于整个概念在前行。
这大概是最好的Spring教程!

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金歌

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表