专栏首页喵叔's 专栏三分钟搞懂依赖注入

三分钟搞懂依赖注入

应用程序通常是由多个组件构成的,组件和组件之间往往存在直接依赖的关系。这种依赖关系看似稳定,但是耦合度很高,如果其中一方不存在的话另一方也就无法工作,而且这种关系也增加了程序的维护成本和灵活性,同时也增加了单元测试的难度。那么,如何解决这个问题呢?这里我们就引入了依赖注入,下面我们通过一个例子来一步一步讲解。 例子很简单,下面这段代码将会向控制台输出一段话,这段话是从 Service 服务中获取的。

public class Demo
{
    public void ShowMessage()
    {
        DataService dataService = new DataService();
        string message = dataService.getMessage();
        Console.Write(message);
    }
}

在不使用依赖注入的情况下,我们通常就会上面这样编写代码,这段代码就像我前面所说的那样,如果 DataService 不存在或者 getMessage 不存在,那么这段代码是无法运行和编译的。下面我们就使用依赖注入的方式来解决这个问题。依赖注入的核心原则是高层不应直接依赖底层,两者均应依赖抽象或接口。根据这个核心原则我们分析前面的代码可知 ShowMessage (高层) 依赖于 DataService (底层),这时我们就需要将 DataService 替换成接口,高层将不会依赖于底层而是依赖于接口,此时高层只关心接口,而不去关心具体的实现,这就形成了 依赖倒置 。基于此,我们定义一个 IDataService 接口,然后 DataService 来实现这个接口。

public interface IDataService
{
    string getMessage();
}

public class DataService : IDataService
{
    public string getMessage()
    {
        return "Hi, I am Jack!";
    }
}

接下来我们在 Demo 中使用依赖注入:

public class Demo
{
    private readonly IDataService dataService;
    public Demo(IDataService dataService)
    {
        this.dataService = dataService;
    }
    public void ShowMessage()
    {
        string message = dataService.getMessage();
        Console.Write(message);
    }
}

我们在上面的代码中通过构造函数向 Demo 中注入了所需的依赖,这种通过构造方法注入依赖的方式称为 构造函数注入 ,是最常见的方式。通过构造函数获得需要依赖是类级别的全局变量,可以在整个类内部使用,并且构造函数注入遵循了显示依赖原则。除了构造函数注入外,还存在另外两种注入方式:属性注入和方法注入。属性注入是通过设置类属性来获取所需的依赖,属性注入虽然看起来和构造函数注入类似,但是它不需要显示的提供依赖,只要在已经实例化的对象上设置相应的属性即可,但是这样做会存在问题,因为依赖项属性设置的值不是强制性的,因此很容易忘记设置从而引发异常。方法注入则是通过在方法的参数中传入所需的依赖,需要注意的是这个方法必须是 public 类型。 当程序中有很多个地方需要用到依赖注入时,我们就需要一个类来专门负责管理创建所需的类,并创建它所有可能用到的依赖,这个类就是依赖注入容器。我们可以把依赖注入容器看作一个创建对象的工厂,负责向外提供被请求要创建的对象,同时提供对象生命周期的管理。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Entity Framework Core 实现全局查询过滤

    微软在 Entity Framework Core 2+ 中引入了全局查询过滤器,简化了构建多租户应用程序和实体软删除的复杂度。这篇文章我将通过代码的形式对全局...

    喵叔
  • TensorFlow学习笔记--自定义图像识别

    本篇文章主要讲解自己的图像数据如何在TnesorFlow上训练,主要从数据准备、训练模型、验证准确率和导出模型并对图片分类。重点如下:

    喵叔
  • 线程基础必知必会(二)

    这篇文章将在上篇文章的基础上,进一步讲解线程的相关知识。这篇文章涉及到的知识点有 线程优先级、前台与后台线程、线程参数、lock、Monitor 和 线程异常处...

    喵叔
  • 物联网智慧养老 玄武给出样本——建平台虚拟运营养老院,全区养老相关资源共享

    随着南京老龄人口越来越多,养老问题也成了社会的热点话题,每个家庭面临的养老问题也各不相同。昨天,玄武区的互联网+智慧养老就吸引来了上海的“考察学习团”,那么到底...

    企鹅号小编
  • Spring官网阅读(二)(依赖注入及方法注入)

    依赖注入测试setter方法注入测试构造函数注入疑问:区别:方法注入:为什么需要方法注入:通过注入上下文(applicationContext对象)通过@Loo...

    程序员DMZ
  • Spring官网阅读系列(二):Spring依赖注入及方法注入

    上篇文章我们学习了官网中的1.2,1.3两小节,主要是涉及了容器,以及Spring实例化对象的一些知识。这篇文章我们继续学习Spring官网,主要是针对1.4小...

    秃顶的Java程序员
  • 会员定价-三个学了就能用的大招

    | 导语 在会员服务的极简公式:收入=付费用户数*客单价,上面玩来玩去也绕不开客单价的问题。今天就近期的有效实战经验来分享下调整会员定价提高客单价的几个关键作...

    腾讯大讲堂
  • 排列组合

    对有n个元素的集合S中的其中r个元素进行排列(n >= r)可以用如下几种方法来理解:

    欧阳大哥2013
  • Leetcode 190 Reverse Bits

    Reverse bits of a given 32 bits unsigned integer. For example, given input 432...

    triplebee
  • 每天一道剑指offer-最小的K个数

    今天的题目 每天的题目见github(看最新的日期): https://github.com/gzc426 具体的题目可以去牛客网对应专题去找。

    乔戈里

扫码关注云+社区

领取腾讯云代金券