当前位置: 首页 > article >正文

【设计模式】依赖注入(Dependency Injection, DI)

依赖注入(Dependency Injection, DI)是一种软件设计模式,用于实现对象之间的松耦合,同时提升代码的可测试性和可维护性。它主要用于管理和提供对象的依赖关系,而不需要在代码中手动创建依赖实例。

核心概念

  • 依赖:一个类需要的服务或对象。例如,类 A 需要类 B 提供某些功能,那么 B 就是 A 的依赖。
  • 注入:将依赖通过外部方式传递给类,而不是让类直接创建或获取这些依赖。

在传统编程中,如果类 A 需要使用类 B,通常会在 A 中直接创建一个 B 的实例。这种方式称为“紧耦合”,会导致以下问题:

  1. 难以测试:无法轻松替换 B 的实现进行单元测试。
  2. 难以扩展:修改 B 的实现可能需要更改 A 的代码。
  3. 依赖管理困难:多个类之间的依赖关系可能变得复杂且难以维护。

依赖注入通过将依赖的创建工作交给外部框架或容器解决了这些问题。


实现依赖注入的方法

  1. 构造函数注入(Constructor Injection) 在构造函数中通过参数传递依赖对象。

    public class A
    {
        private readonly B _b;
    
        public A(B b)
        {
            _b = b;
        }
    
        public void DoSomething()
        {
            _b.SomeMethod();
        }
    }
    
  2. 属性注入(Property Injection) 通过公共属性设置依赖。

    public class A
    {
        public B B { get; set; }
    
        public void DoSomething()
        {
            B?.SomeMethod();
        }
    }
    
  3. 方法注入(Method Injection) 通过方法参数传递依赖。

    public class A
    {
        public void DoSomething(B b)
        {
            b.SomeMethod();
        }
    }
    

DI 容器的作用

在 C# 中,依赖注入通常结合 DI 容器使用,比如 Microsoft 提供的 ASP.NET Core 自带 DI 容器 或第三方库(如 Autofac、Ninject)。DI 容器的主要功能是:

  1. 管理依赖关系。
  2. 自动创建对象并注入其依赖。
  3. 提供对象的生命周期管理(例如单例、瞬态、作用域)。

以下是 ASP.NET Core 的 DI 示例:

// 服务接口
public interface IService
{
    void Serve();
}

// 服务实现
public class Service : IService
{
    public void Serve()
    {
        Console.WriteLine("Service Called");
    }
}

// 使用服务的控制器
public class Controller
{
    private readonly IService _service;

    public Controller(IService service)
    {
        _service = service;
    }

    public void Action()
    {
        _service.Serve();
    }
}

// 程序入口
class Program
{
    static void Main(string[] args)
    {
        // 创建 DI 容器
        var serviceProvider = new ServiceCollection()
            .AddTransient<IService, Service>() // 注册服务
            .BuildServiceProvider();

        // 从容器中获取控制器
        var controller = new Controller(serviceProvider.GetService<IService>());

        controller.Action();
    }
}

优点

  1. 松耦合:对象不直接依赖具体实现,而是依赖于接口或抽象。
  2. 更易测试:通过注入模拟对象(Mocks),轻松进行单元测试。
  3. 可维护性和扩展性更好:更容易修改或扩展应用程序。

适用场景

  • 复杂应用程序:需要管理大量依赖关系时。
  • 单元测试驱动开发(TDD):依赖注入便于注入 mock 对象。
  • 分层架构或微服务:减少模块间的耦合。

通过依赖注入,可以有效改善代码的结构和质量,使开发过程更高效、灵活。


http://www.kler.cn/a/465159.html

相关文章:

  • lec7-路由与路由器
  • Python爬虫 - 豆瓣图书数据爬取、处理与存储
  • 【MongoDB详解】
  • 250103-逻辑运算符
  • 服务器数据恢复—服务器硬盘亮黄灯的数据恢复案例
  • 探索 Vue.js 的动态样式与交互:一个有趣的样式调整应用
  • Spring 中注入 Bean 的方式推荐
  • 【three.js】搭建环境
  • 详细讲一下React中Redux的持久化存储(Redux-persist)
  • 分析服务器 systemctl 启动gozero项目报错的解决方案
  • bilibili 哔哩哔哩小游戏SDK接入
  • 黑马商城:RabbitMQ基础
  • 在K8S中,Pod请求另一个Pod偶尔出现超市或延迟,如何排查?
  • 试题转excel;word转excel;大风车excel(1.1更新)
  • Linux 系统常见问题
  • sklearn_pandas.DataFrameMapper的用法
  • [算法] [leetcode-215] 数组中的第K个最大元素
  • wx015基于springboot+vue+uniapp的经济新闻资讯的设计与实现
  • 虚拟电厂搭建指南:绿虫仿真设计软件的助力
  • 【MySQL】什么是事务?MVCC?
  • Ceph对象存储接口的路线
  • 直观解读 JuiceFS 的数据和元数据设计(一)
  • LWM2M---Wakaama源码对接华为云平台
  • 推荐几个 docker 镜像加速地址
  • 【Vue】Composition API 钩子
  • vim、watch、cp和mv