依赖倒置,控制反转,依赖注入 其实很简单

简介: 上层模块不应该依赖于底层模块,它们都应该依赖于抽象抽象不应该依赖于细节,细节应该依赖于抽象

先用一句最简单(粗暴)解释 开篇


  • 上层模块不应该依赖于底层模块,它们都应该依赖于抽象
  • 抽象不应该依赖于细节,细节应该依赖于抽象


首先,让我们持有以下几个问题:

什么是依赖倒置?
什么是控制反转
什么是依赖注入

说实话,刚看到这几个词的时候,不知道到底是啥意思,直到多翻了几篇之后,才恍然大悟,哦,原来我经常在用啊。于是记录一下我的理解。


本篇可以帮你理清这几个关键词的意义,重新梳理自己的思想。

什么是依赖倒置呢?

  • 上层模块不应该依赖于底层模块,它们都应该依赖于抽象


初学者看到这句解释,估计都想骂人了。而我们大多数同学往往总是解释时带着这句话,的确言简意赅。


我个人的理解:依赖倒置其实就相当于是 面向接口开发的 一种体现。


听起来很高大上,我直接用两段代码一探究竟吧:

public class Test {
    public static void main(String[] args) {
        Teacher teacher=new Teacher();
        teacher.initWang();
    }
}
/* 体育老师 */
class Teacher{
    private Wang wang;
    public void initWang(){
        wang=new Wang();
        wang.play();
    }
}
/* 喜欢的运动 */
interface IMotion {
    void play();
}
/* 学生 */
class Wang implements IMotion{
    @Override
    public void play() {
        System.out.println("wang 喜欢 踢足球");
    }
}

在上面的代码中,我们有一个测试类 Test,和一个体育老师类 Teacher , IMotion的运动接口,和一个学生Wang

运行我们的Test测试例子,会打印 ”wang 喜欢 踢足球“;

如果我们现在想再加入一个学生 Li,这个时候就需要更改 Teacher类了,比如再增加一个方法 initLi。


如下:

/* 体育老师 */
class Teacher{
    private Wang wang;
    private Li li;
    public void initWang(){
        wang=new Wang();
        wang.play();
    }
    public void initLi(){
        li=new Li();
        li.play();
    }
}
/* 学生 */
class Li implements IMotion{
    @Override
    public void play() {
        System.out.println("li 喜欢 打篮球");
    }
}

我知道有些同学现在可能想骂了,这个博主是傻子吗,直接不会用接口对象吗。别急,我们慢慢过渡。

依赖倒置版本

public class Test {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.play();
    }
}
/* 体育老师 */
class Teacher {
    private IMotion iMotionWang;
    private IMotion iMotionLi;
    public Teacher(){
        iMotionLi=new Li();
        iMotionWang=new Wang();
    }
    public void play() {
        iMotionWang.play();
        iMotionLi.play();
    }
}

有些同学可能就要喊了?这不就我经常写的吗,这就叫  依赖倒置

没错,你没有理解错,虽然这个demo现在还存一些问题(比如谁没事new两个接口),但是它已经 具备了依赖倒置的思想

在前面的版本,我们一直new 的是具体的实例,针对具体的学生去操作,而现在我们应对的是它的抽象类,我们的的思想其实已经改变了。

那有些同学可能会问了,那这句话抽象不应该依赖于细节,细节应该依赖于抽象你怎么解释?

仔细思考一下,我们刚才写的这个接口,是不是就是这个理念,Teacher 老师类需要的是 学生具体喜欢的运动这个行为,在接口的形式下,我们无论增加多少学生,都不会影响老师这个类(不要注意多个new)。

接下来我们再来看看第二个特性,控制反转:

我们再更改一下刚才的代码,如下:

public class Test {
    public static void main(String[] args) {
        Teacher teacher = new Teacher(new Wang());
        teacher.play();
    }
}
/* 体育老师 */
class Teacher {
    private IMotion iMotion;
    public Teacher(IMotion iMotion) {
        this.iMotion = iMotion;
    }
    public void play() {
        iMotion.play();
    }
}

大多数同学肯定又要喊了,这不就是我经常写代码时的版本吗,这就是控制反转?你骗谁呢?

没毛病,这个真的是控制反转,再对比一下上一个版本,我们将 new 的这一步交给了具体的测试类,而不用 Teacher类来操作,这样无论以后增加多少个学生类,Teacher 都不用更改。

我们再来看看 依赖注入:

其实我们刚在已经做了依赖注入,比如我们通过构造函数将 具体的 对象 传了进去。当然也可以通过 set 方法传递;

如下:

public class Test {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.setiMotion(new Wang());
        teacher.play();
    }
}
/* 体育老师 */
class Teacher {
    private IMotion iMotion;
    public void setiMotion(IMotion iMotion) {
        this.iMotion = iMotion;
    }
    public void play() {
        iMotion.play();
    }
}

看完上面是不是觉得很简单,依赖倒置其实也没什么吗,没错,其实只要我们遵循设计模式,其实这些所谓的名词也没什么。上面的demo虽然看起来很简单,但是大家关注的点不应该在缺陷的demo上,而应该在代码的过渡上面,我们现在看这些操作,觉得很简单,那是因为我们已经写了太多业务代码,设计模式肯定经常涉及,所以觉得不难。

如果是新同学的话,我建议你仔细感受过渡的过程,体会面向接口开发的快乐。

当然以上这只是我个人的理解,如果有偏差,也希望大家不吝赐教。

目录
相关文章
|
XML Java 数据格式
依赖注入~
依赖注入~
|
5月前
|
设计模式 测试技术 容器
依赖注入与控制反转:理解与应用
【8月更文挑战第22天】
197 0
|
5月前
|
设计模式 Java 容器
控制反转 (IoC)
【8月更文挑战第24天】
45 0
|
XML 开发框架 Java
Spring框架IoC控制反转
Spring是与2003年兴起的一个轻量级的Java开发框架,它是为了解决企业应用开发的复杂性而创建的。Spring的核心是控制反转(IOC)和面向切面编程(AOP)。Spring是可以在Java SE/EE中使用的轻量级开源框架。 Spring的主要作用就是为代码"解耦",降低代码间的耦合度。就是让对象和对象(模板和模板)之间关系不是使用代码关联,而是通过配置来说明。即在Spring中说明对象(模块)的关系。 Spring根据代码的功能特点,使用IOC降低业务对象之间耦合度。IOC使得主业务在相互调用过程中,不用再自己维护关系了,即不用再自己创建要使用的对象了,而是由Spring容器统一
88 2
|
设计模式 Java Spring
【设计模式】依赖倒置原则与工厂方法模式与spring
【设计模式】依赖倒置原则与工厂方法模式与spring
131 0
|
JavaScript uml 容器
Ioc——控制反转
Ioc——控制反转
213 0
Ioc——控制反转
|
程序员 容器
控制反转与依赖注入
控制反转与依赖注入
135 0
控制反转与依赖注入
|
SQL 开发框架 安全
3.1依赖注入
传统开发中,对象都是开发者创建组装,开发者必须了解各类的使用方法且某些类的耦合度较高,例如想把sql serve数据库改为MySql数据库则需要更改某些代码。控制反转的目的是让框架完成对象的创建和组装。从“我创建对象”编程“我要对象”
122 0
|
XML 架构师 关系型数据库
|
自动驾驶 小程序 Java
什么是控制反转(IOC)?什么是依赖注入?
什么是控制反转(IOC)?什么是依赖注入?
什么是控制反转(IOC)?什么是依赖注入?