IoC 思想简单而深邃

server/2024/10/20 7:15:25/

一、序言

本文跟大家聊聊 IoC 这一简单而深邃的思想。

二、依赖倒置原则

软件工程理论中共有六大设计原则:

  1. 单一职责原则:不存在多于一个的因素导致类的状态发生变更,即一个类只负责一项单一的职责。
  2. 里氏替换原则:基类出现的地方都可以用其子类进行替换,而不会引起任何不适的问题。
  3. 接口隔离原则:客户端不应该依赖于其不需要的接口,类之间的依赖关系应该建立在最小的接口之上。
  4. 迪米特法则:一个对象对其他对象有最少的了解。
  5. 开闭原则:软件设计对于扩展是开发的,即模块的行为是可以扩展的。软件设计对于修改是关闭的,即模块的行为是不可修改的。
  6. 依赖倒置原则:高层次的模块不应该依赖于低层次的模块,都应该依赖于抽象。

今天我们只讨论依赖倒置原则。上面对于依赖倒置原则的绕口令我们先暂时放下。

场景假设:一个人通过一种交通工具上下班。

  1. 若不遵循依赖倒置原则,实现方案如下:

    居住地离公司较近时:

    // 自行车类
    public class Bike {public void go() {System.out.println("骑自行车");}
    }public class Person {// 自行车private Bike bike;// 构造器public Person() {this.bike = new Bike();}// 上班public void goToWork() {bike.go();}}
    

    居住地离公司较远时:

    // 公交车类
    public class Bus {public void go() {System.out.println("乘坐公交车");}
    }public class Person {// 公交车private Bus bus; // 构造器public Person() {this.bus = new Bus();}// 上班public void goToWork() {bus.go();}
    }
    

    不遵循依赖倒置原则时,我们发现了一个巨大的问题:每换一次交通工具,Person 类几乎是重构了一遍。

  2. 遵循依赖倒置原则,实现方案如下:

    交通工具会有很多,我们将其进行一次抽象:

    // 交通工具接口
    public interface Vehicle {// 出发void go();
    }
    

    居住地离公司较近时:

    // 自行车类
    public class Bike implements Vehicle {@Overridepublic void go() {System.out.println("骑自行车");}
    }public class Person {// 此处放抽象接口private Vehicle vehicle;// 构造器public Person() {// 抽象接口的实现类是自行车this.vehicle = new Bike();}// 上班public void goToWork() {vehicle.go();}}
    

    居住地离公司较远时:

    // 公交车类
    public class Bus implements Vehicle {@Overridepublic void go() {System.out.println("乘坐公交车");}
    }public class Person {// 此处放抽象接口private Vehicle vehicle;// 构造器public Person() {// 抽象接口的实现类是公交车this.vehicle = new Bus();}// 上班public void goToWork() {vehicle.go();}
    }
    

    当我们采用依赖倒置原则实现方案时,可以发现除了构造器中需要修改,其他部分不需要做任何的修改。

现在我们重新看一下依赖倒置原则那段绕口令。高层次的模块不应该依赖于低层次的模块,即高层次模块与低层次模块应该解耦,就如同 Person 类和 Bike/Bus 类一样。如果 Person 类中直接依赖 Bike/Bus 类就会出现高耦合。都应该依赖于抽象指的是:为了解耦,高层次的模块应该依赖于低层次模块的抽象而不是具体的低层次模块。就如同 Person 类应该依赖 Vehicle 抽象接口。

IoC__141">三、IoC 思想

当我们遵循依赖倒置原则开发时虽然解决了大部分问题,但是我们发现依旧还存在一些问题:

public class Person {private Vehicle vehicle;public Person() {// 此处每次仍需要修改this.vehicle = new Bus();}public void goToWork() {vehicle.go();}
}

上面的问题是: Person 类依旧需要手动的创建 Bike 或 Bus 对象。有没有一种方式将这种手动的方式变成自动管理,从而进一步实现解耦呢?解决方案就是采用 IoC 思想。

IoC,全称为 Inversion of Control,中文名为“控制反转”,是一种设计思想。其核心思想是:将对象的创建权、管理权移交给容器,而不是开发人员。

Spring 已经将 IoC 思想具象化,我们以 Spring 中的 IoC 容器为例重新分析上述的例子。

// 自行车类
@Component
public class Bike implements Vehicle {@Overridepublic void go() {System.out.println("骑自行车");}
}@Component
public class Person {// 此处放抽象接口@Resourceprivate Vehicle vehicle;// 构造器public Person() {}// 上班public void goToWork() {vehicle.go();}}

从上面的代码中我们可以看出:在 Person 类中我们使用 @Resource注解将 Vehicle 对象的赋值交由 IoC 容器。容器创建 Bike 对象之后将其引用赋给了上述的 vehicle 变量。至此,对象与对象之间的完全解耦实现了。

IoC__7pnghttpsimgblogcsdnimgcnimg_convertca98b6db7500d99c39348fa987845512png_193">四、IoC 思想工作流程的具象化未命名文件 (7).png

  1. 开发人员向 IoC 容器声明需要的对象
  2. IoC 容器维护所有对象之间的关系,以及对象的创建时机
  3. 开发人员需要对象时直接从 IoC 容器中获取(获取到的对象与其他对象的关系已由 IoC 容器维护好)

往期推荐

  1. JDK 动态代理
  2. ThreadLocal
  3. HashMap 源码分析(三)
  4. Spring 三级缓存
  5. RBAC 权限设计(二)

http://www.ppmy.cn/server/6308.html

相关文章

SpringBoot集成WebService

Spring集成Webservice(JAXWS) 初步尝试 引入依赖 dependencies {// 引入Spring Boot Web Starter,提供基础的Web应用支持,包括Tomcat服务器、Spring MVC等组件 implementation("org.springframework.boot:spring-boot-star…

Sulley入门教学——简介、安装(Win7、VMware)

1、简介 Sulley 是由 Pedram Amini 和 Aaron Portnoy 开发的开源工具。它以 Python 编写,可以轻松地在不同平台上部署和使用。Sulley 提供了一个灵活且功能强大的框架,允许用户定义协议消息的结构、字段类型、边界条件和模糊测试策略。用户可以使用 Sul…

【SpringBoot】Spring Boot 项目中整合 MyBatis 和 PageHelper

目录 前言 步骤 1: 添加依赖 步骤 2: 配置数据源和 MyBatis 步骤 3: 配置 PageHelper 步骤 4: 使用 PageHelper 进行分页查询 IDEA指定端口启动 总结 前言 Spring Boot 与 MyBatis 的整合是 Java 开发中常见的需求,特别是在使用分页插件如 P…

【单调栈】力扣85.最大矩形

好久没更新了 ~ 我又回来啦! 两个好消息: 我考上研了,收到拟录取通知啦!开放 留言功能 了,小伙伴对于内容有什么疑问可以在文章底部评论,看到之后会及时回复大家的! 前面更新过的算法&#x…

EXCEL VBA限制工作数据批号或者自定义规则完整

EXCEL VBA限制工作数据批号或者自定义规则完整 Private Sub Worksheet_Change(ByVal Target As Range)Dim nRow%, Arr(), cMc$, cPc$, cTxt$, nSum!If Target.Row 1 Or Target.Column <> 4 Then Exit SubIf Target.CountLarge > 1 Then Exit SubcMc Target.Offset(0…

基于Hadoop的石油大数据平台设计

基于Hadoop的石油大数据平台设计 Design of an oil big data platform based on Hadoop 完整下载链接:基于Hadoop的石油大数据平台设计 文章目录 基于Hadoop的石油大数据平台设计摘要第一章 绪论1.1 研究背景1.2 研究意义1.3 国内外研究现状1.4 本文研究内容与结构 第二章 Ha…

Java快速排序知识点(含面试大厂题和源码)

快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;采用分治法&#xff08;Divide and Conquer&#xff09;的策略来对一个数组进行排序。快速排序的平均时间复杂度为 O(n log n)&#xff0c;在最坏的情况下为 O(n^2)&#xff0c;但这种情况很少发生…

【php快速上手(十一)】

目录 PHP快速上手&#xff08;十一&#xff09;PHP 连接数据库和创建数据库PHP 连接数据库使用 MySQLi连接 MySQL 数据库使用 PDO 连接 MySQL 数据库 PHP创建数据库使用MySQLi创建MySQL数据库&#xff1a;使用PDO创建MySQL数据库&#xff1a; PHP快速上手&#xff08;十一&…