TypeScript中的依赖注入:初学者简明指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

TypeScript中的依赖注入:面向初学者

\n\n

在软件开发领域,经常能听到术语依赖注入(Dependency Injection,简称DI)。对于TypeScript初学者开发者来说,这听起来可能有些吓人,但实际上它是一种简单而强大的设计模式,能让你的代码更清晰、更易测试、更易维护。在本文中,我们将详细讲解什么是DI,为什么需要它,以及如何在TypeScript中实际应用它。

\n\n

什么是依赖注入?

\n\n

想象一下你在组装一台电脑。你不是在工厂里就把处理器直接焊在主板上,而是留下一个插槽,可以插入任何兼容的处理器。依赖注入的工作原理与此类似:类不再自己创建依赖(例如数据库或HTTP客户端),而是从外部获取它们。

\n\n

简单来说,DI就是对象不在内部创建自己的“助手”,而是通过构造函数或方法获取现成的助手。

\n\n

没有DI的问题:紧耦合

\n\n

来看一个实际项目中常见的例子:

\n\n
class UserService {\n    private database: MySQLDatabase;\n\n    constructor() {\n        this.database = new MySQLDatabase(); // 紧耦合!\n    }\n\n    getUser(id: number) {\n        return this.database.findUserById(id);\n    }\n}
\n\n

这里UserService与MySQLDatabase紧密耦合。如果你想改用PostgreSQL,或者想用模拟数据库编写单元测试,就必须重写整个类。这违反了SOLID原则中的开闭原则。

\n\n

使用DI的解决方案:灵活性与可测试性

\n\n

现在,我们用DI重写同一个类:

\n\n
interface Database {\n    findUserById(id: number): User | null;\n}\n\nclass UserService {\n    constructor(private database: Database) {} // 依赖从外部传入\n\n    getUser(id: number) {\n        return this.database.findUserById(id);\n    }\n}\n\n// 使用\nconst mySQL = new MySQLDatabase();\nconst service = new UserService(mySQL); // 注入依赖
\n\n

现在UserService不知道它在使用哪个数据库。你可以轻松地将MySQLDatabase替换为PostgreSQLDatabase或用于测试的MockDatabase。

\n\n

依赖注入的主要方式

\n\n

在TypeScript中,有三种主要的依赖注入方式。我们来逐一了解。

\n\n

1. 构造函数注入(Constructor Injection)

\n\n

这是最常见且推荐的方式。依赖通过类的构造函数传入。

\n\n
class Logger {\n    log(message: string) {\n        console.log(`[LOG]: ${message}`);\n    }\n}\n\nclass OrderService {\n    constructor(private logger: Logger) {}\n\n    createOrder(data: any) {\n        this.logger.log('Order created');\n        // 创建订单的逻辑\n    }\n}\n\nconst logger = new Logger();\nconst orderService = new OrderService(logger);
\n\n

2. 属性注入(Property Injection)

\n\n

依赖在对象创建后直接设置到对象的属性中。这种方式使用较少,因为它可能导致对象初始化不完整。

\n\n
class EmailService {\n    sendEmail(to: string, message: string) {\n        console.log(`Email sent to ${to}: ${message}`);\n    }\n}\n\nclass NotificationService {\n    emailService!: EmailService; // 类型断言\n\n    notifyUser(user: string) {\n        this.emailService.sendEmail(user, 'Hello!');\n    }\n}\n\nconst notification = new NotificationService();\nnotification.emailService = new EmailService(); // 设置属性\nnotification.notifyUser('user@example.com');
\n\n

3. 方法注入(Method Injection)

\n\

博客

书籍推荐