0

0

分解依赖倒置、IoC 和 DI

碧海醫心

碧海醫心

发布时间:2025-01-20 16:38:15

|

1242人浏览过

|

来源于php中文网

原创

分解依赖倒置、ioc 和 di

本文深入探讨 NestJS 依赖注入系统,并阐明依赖倒置原则 (DIP)、控制反转 (IoC) 和依赖注入 (DI) 的概念及其关联。这三个概念看似相似,实则各有侧重,相互关联却又解决不同的问题。本文旨在帮助读者理清这些概念,并理解它们如何协同工作。


  1. 依赖倒置原则 (DIP)

定义:

高层模块不应该依赖于低层模块;两者都应该依赖于抽象。抽象不应该依赖于细节;细节应该依赖于抽象。

含义解读

在软件开发中,高层模块负责核心业务逻辑,而低层模块处理具体的实现细节(例如文件系统、数据库或 API)。若无 DIP,高层模块直接依赖于低层模块,导致紧密耦合,从而:

  • 降低灵活性。
  • 复杂化测试和维护。
  • 难以替换或扩展低层细节。

DIP 颠覆了这种依赖关系。高层和低层模块都依赖于共享的抽象(接口或抽象类),而不是高层模块直接控制低层实现。


无 DIP 示例

Python 示例

<code class="python">class EmailService:
    def send_email(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self):
        self.email_service = EmailService()

    def notify(self, message):
        self.email_service.send_email(message)</code>

TypeScript 示例

<code class="typescript">class EmailService {
    sendEmail(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private emailService: EmailService;

    constructor() {
        this.emailService = new EmailService();
    }

    notify(message: string): void {
        this.emailService.sendEmail(message);
    }
}</code>

问题:

  1. 紧密耦合:Notification 直接依赖 EmailService
  2. 难以扩展:切换到 SMSServicePushNotificationService 需要修改 Notification 类。

含 DIP 示例

Python 示例

<code class="python">from abc import ABC, abstractmethod

class MessageService(ABC):
    @abstractmethod
    def send_message(self, message):
        pass

class EmailService(MessageService):
    def send_message(self, message):
        print(f"Sending email: {message}")

class Notification:
    def __init__(self, message_service: MessageService):
        self.message_service = message_service

    def notify(self, message):
        self.message_service.send_message(message)

# 使用示例
email_service = EmailService()
notification = Notification(email_service)
notification.notify("Hello, Dependency Inversion!")</code>

TypeScript 示例

<code class="typescript">interface MessageService {
    sendMessage(message: string): void;
}

class EmailService implements MessageService {
    sendMessage(message: string): void {
        console.log(`Sending email: ${message}`);
    }
}

class Notification {
    private messageService: MessageService;

    constructor(messageService: MessageService) {
        this.messageService = messageService;
    }

    notify(message: string): void {
        this.messageService.sendMessage(message);
    }
}

// 使用示例
const emailService = new EmailService();
const notification = new Notification(emailService);
notification.notify("Hello, Dependency Inversion!");</code>

DIP 的优势

  • 灵活性:无需修改高层模块即可替换实现。
  • 可测试性:使用模拟对象替换真实依赖项进行测试。
  • 可维护性:低层模块的更改不会影响高层模块。

  1. 控制反转 (IoC)

IoC 是一种设计原则,依赖项的创建和管理由外部系统或框架控制,而不是在类内部进行。

传统编程中,类自行创建和管理依赖项。IoC 将这种控制反转——外部实体(例如框架或容器)管理依赖项,并在需要时注入。

无 IoC 示例

在无 IoC 的场景中,类自行创建和管理依赖项,导致紧密耦合。


Python 示例:无 IoC

<code class="python">class SMSService:
    def send_message(self, message):
        print(f"Sending SMS: {message}")

class Notification:
    def __init__(self):
        self.sms_service = SMSService()

    def notify(self, message):
        self.sms_service.send_message(message)

# 使用示例
notification = Notification()
notification.notify("Hello, tightly coupled dependencies!")</code>

TypeScript 示例:无 IoC

<code class="typescript">class SMSService {
    sendMessage(message: string): void {
        console.log(`Sending SMS: ${message}`);
    }
}

class Notification {
    private smsService: SMSService;

    constructor() {
        this.smsService = new SMSService();
    }

    notify(message: string): void {
        this.smsService.sendMessage(message);
    }
}

// 使用示例
const notification = new Notification();
notification.notify("Hello, tightly coupled dependencies!");</code>

无 IoC 的问题:

AIBox 一站式AI创作平台
AIBox 一站式AI创作平台

AIBox365一站式AI创作平台,支持ChatGPT、GPT4、Claue3、Gemini、Midjourney等国内外大模型

下载
  1. 紧密耦合:Notification 类直接创建并依赖 SMSService 类。
  2. 灵活性低:切换到其他实现需要修改 Notification 类。
  3. 难以测试:模拟依赖项用于单元测试比较困难,因为依赖项是硬编码的。

使用 IoC

在使用 IoC 的示例中,依赖关系的管理责任转移到外部系统或框架,实现松散耦合并增强可测试性。


Python 示例:使用 IoC

<code class="python">class SMSService:
    def send_message(self, message):
        print(f"Sending SMS: {message}")

class Notification:
    def __init__(self, message_service):
        self.message_service = message_service

    def notify(self, message):
        self.message_service.send_message(message)

# IoC: 依赖项由外部控制
sms_service = SMSService()
notification = Notification(sms_service)
notification.notify("Hello, Inversion of Control!")</code>

TypeScript 示例:使用 IoC

<code class="typescript">class SMSService {
    sendMessage(message: string): void {
        console.log(`Sending SMS: ${message}`);
    }
}

class Notification {
    private messageService: SMSService;

    constructor(messageService: SMSService) {
        this.messageService = messageService;
    }

    notify(message: string): void {
        this.messageService.sendMessage(message);
    }
}

// IoC: 依赖项由外部控制
const smsService = new SMSService();
const notification = new Notification(smsService);
notification.notify("Hello, Inversion of Control!");</code>

IoC 的优势:

  1. 松散耦合:类不创建其依赖项,从而减少对特定实现的依赖。
  2. 易于切换实现:用 EmailService 替换 SMSService 而无需修改核心类。
  3. 提高可测试性:在测试期间注入模拟或 Mock 依赖项。

  1. 依赖注入 (DI)

DI 是一种技术,对象从外部源接收其依赖项,而不是自己创建它们。

DI 是 IoC 的一种实现方式。它允许开发人员通过多种方式将依赖项“注入”到类中:

  1. 构造函数注入:依赖项通过构造函数传递。
  2. Setter 注入:依赖项通过公共方法设置。
  3. 接口注入:依赖项通过接口提供。

Python 示例:使用 DI 框架

使用 injector 库:

<code class="python">from injector import Injector, inject

class EmailService:
    def send_message(self, message):
        print(f"Email sent: {message}")

class Notification:
    @inject
    def __init__(self, email_service: EmailService):
        self.email_service = email_service

    def notify(self, message):
        self.email_service.send_message(message)

# DI 容器
injector = Injector()
notification = injector.get(Notification)
notification.notify("This is Dependency Injection in Python!")
</code>

TypeScript 示例:使用 DI 框架

使用 tsyringe

<code class="typescript">import "reflect-metadata";
import { injectable, inject, container } from "tsyringe";

@injectable()
class EmailService {
    sendMessage(message: string): void {
        console.log(`Email sent: ${message}`);
    }
}

@injectable()
class Notification {
    constructor(@inject(EmailService) private emailService: EmailService) {}

    notify(message: string): void {
        this.emailService.sendMessage(message);
    }
}

// DI 容器
const notification = container.resolve(Notification);
notification.notify("This is Dependency Injection in TypeScript!");</code>

DI 的优势:

  • 简化测试:轻松使用模拟对象替换依赖项。
  • 高可扩展性:添加新的实现而无需修改现有代码。
  • 增强可维护性:减少系统某一部分变更的影响。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

49

2026.02.13

TypeScript全栈项目架构与接口规范设计
TypeScript全栈项目架构与接口规范设计

本专题面向全栈开发者,系统讲解基于 TypeScript 构建前后端统一技术栈的工程化实践。内容涵盖项目分层设计、接口协议规范、类型共享机制、错误码体系设计、接口自动化生成与文档维护方案。通过完整项目示例,帮助开发者构建结构清晰、类型安全、易维护的现代全栈应用架构。

196

2026.02.25

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

39

2026.03.13

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1958

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

658

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2401

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

47

2026.01.19

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

389

2023.06.29

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号