Java进阶学习笔记(十一)胎教级别的依赖注入(DI)和控制反转(IOC)思想讲解

本文深入解析Java开发中的依赖注入(DI)和控制反转(IOC)概念,通过实例讲解了依赖注入的基本原理,以及控制反转如何改变对象之间的依赖关系,使代码更灵活、易于维护。

参考轻松理解 Java开发中的依赖注入(DI)和控制反转(IOC)Java:控制反转(IoC)与依赖注入(DI)依赖注入Dependency Injection-依赖注入详解

一、依赖注入

依赖注入是一个常见的专业名词,但是较难理解。我觉得这个是因为依赖注入这个思想,其实就藏在面对对象的编程中。

就好像每个人都会吃饭,但有一天突然要你科学解释,什么叫做咀嚼,你肯定也会不知所措。

所以个人感觉可以解释为:注入依赖对象。

1、什么叫注入

有些人对于注入不太理解。用一个简单的例子来解释一下

我们有个Task类

public class Task {
    private String taskName;

    public Task(String taskName) {
        this.taskName = taskName;
    }
}

此时我们main函数的代码如下所示:

    public static void main(String[] args) {
        Task task = new Task("Task #1");
    }

Task的name,从main函数输入,这种行为就叫做注入。

2、什么是依赖

我们先建立一个Java程序员类

public class Javaer {
    private String name = "张三";
    public void writeCode() {
        System.out.println(this.name + " is writing java code");
    }
}

我们修改Task代码如下

public class Task {
    private String taskName;
    private Javaer javaer;

    public Task(String taskName) {
        this.taskName = taskName;
        this.javaer = new Javaer("张三");
    }
    public void start() {
        System.out.println("Task " + this.taskName + " started");
        javaer.writeCode();
    }
}

Task有了Javaer属性,Javaer就叫做Task的依赖。

进一步解释就是:任务需要依赖程序员完成,现在Task,有了Javaer类这个属性,需要Javaer类的帮助,才能完成自己的start()功能。

Task里面this.javaer = new Javaer("张三");,这以后我们想要李四来完成任务的时候,我们应该怎么办,如果是面向过程的变成思想,最终会变成以下代码

public class Task {
    private String taskName;
    private Javaer javaer;

    public Task(String taskName) {
        this.taskName = taskName;
    }
    public void zhangSanStart() {
        this.javaer = new Javaer("张三");
        System.out.println("Task " + this.taskName + " started");
        javaer.writeCode();
    }

    public void liSiStart() {
        this.javaer = new Javaer("李四");
        System.out.println("Task " + this.taskName + " started");
        javaer.writeCode();
    }
}

main调用如下

    public static void main(String[] args) {
        Task task = new Task("任务名1");
        task.zhangSanStart();

        Task task2 = new Task("任务名2");
        task2.liSiStart();
    }

结果如下

Task 任务名1 started
张三 is writing java code
Task 任务名2 started
李四 is writing java code

一切看似正常运行,但以后要王五,赵六来完成任务的时候,岂不是需要一直修改Task代码?
这时候就需要依赖注入。

3、依赖注入介绍

有些人可能明白了,依赖注入就是同时拥有依赖、注入。
现在我们再次对Task进行修改

public class Task {
    private String taskName;
    private Javaer javaer;

    public Task(String taskName, Javaer javaer) {
        this.taskName = taskName;
        this.javaer = javaer;
    }
    public void start() {
        System.out.println("Task " + this.taskName + " started");
        this.javaer.writeCode();
    }
}

main如下所示

    public static void main(String[] args) {
        Javaer javaer = new Javaer("张三");
        Task task = new Task("任务一", javaer);
        task.start();
    }

结合我们之前的所说,注入是其它函数的输入,若注入的是依赖呢?
就叫做依赖注入。

二、控制反转

反转的意思比较好理解,就是从主动,变为被动。
现在我们的Task,只能由Java程序员完成,我们若要让Php程序员完成要怎么做呢?

方案一(不好的方案)

新建一个Phper类

public class Phper {
    private String name;

    public Phper(String name) {
        this.name = name;
    }

    public void writeCode() {
        System.out.println(this.name + " is writing php code");
    }
}

修改我们的Task类

public class Task {
    private String taskName;
    private Javaer javaer;
    private Phper phper;

    public Task(String taskName) {
        this.taskName = taskName;
    }

    public void javaerStart() {
        System.out.println("javaer start work");
        this.javaer.writeCode();
    }

    public void phperStart() {
        System.out.println("phper start work");
        this.phper.writeCode();
    }


    public void setJavaer(Javaer javaer) {
        this.javaer = javaer;
    }

    public void setPhper(Phper phper) {
        this.phper = phper;
    }
}

我们的main函数

    public static void main(String[] args) {
        Javaer javaer = new Javaer("java程序员");
        Phper phper = new Phper("php程序员");

        Task task = new Task("新任务");
        task.setJavaer(javaer);
        task.javaerStart();

        Task task2 = new Task("新任务2");
        task2.setPhper(phper);
        task2.phperStart();
    }

运行结果

javaer start work
java程序员 is writing java code
phper start work
php程序员 is writing php code

可以看见,程序正确运行,但如果要添加C程序员的时候,我们就除了添加C程序员的类以外,还需要修改Task,这并不是我们希望的。

方案2(好方案,控制反转)

涉及接口和多态,不太熟悉的朋友建议参考这篇文章Java接口 | 菜鸟教程
由于Javaer和Phper等等,都是程序员,我们新建一个接口Coder。

public interface Coder {
    public void writeCode();
}

修改javaer和phper,让其都实现coder接口(关于继承不懂的可以看这篇文章)

public class Javaer implements Coder {
    private String name;

    public Javaer(String name) {
        this.name = name;
    }

    @Override
    public void writeCode() {
        System.out.println(this.name + " is writing java code");
    }
}
public class Phper implements Coder {
    private String name;

    public Phper(String name) {
        this.name = name;
    }

    @Override
    public void writeCode() {
        System.out.println(this.name + " is writing php code");
    }
}

Task如下所示

public class Task {
    private String taskName;
    private Coder coder;

    public Task(String taskName) {
        this.taskName = taskName;
    }

    public void setCoder(Coder coder) {
        this.coder = coder;
    }
    
    public void start() {
        System.out.println("Task " + this.taskName + " start");
        this.coder.writeCode();
    }
}

主函数如下所示

    public static void main(String[] args) {
        Javaer javaer = new Javaer("java程序员");
        Phper phper = new Phper("php程序员");

        Task task = new Task("新任务");
        task.setCoder(javaer);
        task.start();

        Task task2 = new Task("新任务2");
        task2.setCoder(phper);
        task2.start();
    }
Task 新任务 start
java程序员 is writing java code
Task 新任务2 start
php程序员 is writing php code

我们可以发现,原本是Task类,指定执行者,现在Task类的执行者是被其他代码指定,Task交出赋值权, 从主动赋值到被动赋值, 这就是控制反转。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值