一个例子理解依赖注入

前言

之前已经记录过一篇文章解释依赖注入,现在看来有点过于理论化,于是写了一个demo解释下什么是依赖注入,也是在实际开发中依赖注入的使用场景。

对依赖注入还完全不理解的可以看一下上一篇文章:依赖注入 简介

场景

假设目前你正在开发公司的一个框架,为了保证线上代码的安全,你需要引入你们公司的“线上开关”的模块,这样如果发现你的框架有问题,可以及时用线上开关关闭部分功能,而不至于在下个版本发布前让问题一直存在。

一般情况下,开发就会直接依赖这个“线上开关”的模块,然后直接调用相关方法来判断是否要关闭部分功能。
这是最简单的实现方式,但是这样的方式会让你的库与“线上开关”的库耦合起来。
简单说几个真实存在问题:

  1. “线上开关”库更新了版本,更改了调用的API,原来的API废弃。那么你的库即使没有任何修改,你也必须更新你的库中依赖的“线上开关”的库。
  2. “线上开关”库更改了API中的数据结构,导致你的库中引用该API 的地方出了问题,而这对于“线上开关”这个库的开发人员是不可见的,他们不可能每个改动都要测下每个引用过他们的其他库。(你不能总是心里默认其他开发人员会去兼容以前的版本)

解决方式

解决步骤:

  1. 你的库中创建一个依赖注入类,一般是个单例。在库中引用这个单例的各个方法,这些方法由于可能会依赖其他库,因此不在库中直接实现,放到基础项目中去实现。
  2. 在基础项目中实现这个单例。

这样的好处有以下几点:

  1. 你不用依赖基础库之外的其他开发人员负责的库。因此你的项目也不会与其他库耦合,同时也一定程度上减小了你的库的大小。
  2. 把这个类的实现放到基础项目中,这样其他库的修改如果导致你的项目出了问题,其他库的开发人员也能注意到。

代码例子

impl包:基础项目代码。
testFrame包:使用依赖注入的库,即上面说的,你开发的那个库。

myFrame.java:你的框架的代码。
TestDependent.java:你的库中依赖注入的类。

TestMain.java:基础项目中的main方法。
TestDependentImpl.java:在基础项目中实现的依赖注入的类。
在这里插入图片描述

框架代码

myFrame

public class myFrame {

    public void runPrint(){
        if(TestDependent.getInstance().isCanRun()){
            System.out.println("frame run");
        }
    }
}

TestDependent

public class TestDependent {

    private static TestDependent instance;

    public static void setInstance(TestDependent instance) {
        TestDependent.instance = instance;
    }

    public static TestDependent getInstance() {
        if(instance==null){
            instance=new TestDependent();
        }

        return instance;
    }

    public boolean isCanRun(){
        return true;
    }
}

基础项目代码

TestMain

public class TestMain {

    public static void main(String[] args){

        //首先设置自己的依赖注入类
        TestDependent.setInstance(new TestDependentImpl());

        //调用框架
        new myFrame().runPrint();
    }
}

TestDependentImpl

public class TestDependentImpl extends TestDependent {
    @Override
    public boolean isCanRun() {
        //执行线上开关逻辑,判断返回值
//        if(){
//            return true;
//        }else{
//            return false;
//        }
        return false;
    }
}

总结

最终的流程是这样的:

  1. 你的库每次需要其他的依赖都会去TestDependent这个单例中拿。
  2. 由于基础项目中自己实现并覆盖了TestDependent这个单例,因此你的库实际是去TestDependentImpl中拿的。
  3. 这样不仅你的库与其他的库解耦了,其他的库的改动产生的问题也会第一时间反馈在基础项目上。

小tip
TestDependent为什么不用抽象类?
因为每个方法需要设置一个默认值,你要保证即使基础项目中不实现这个依赖注入类,你的库也能正常运行。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值