Question 91
Question
Explain how to implement a simple dependency injection container.
Answer
Why Dependency Injection?
Loose Coupling: DI promotes loose coupling between components. Instead of classes directly creating their dependencies, they receive them as parameters. This makes code more modular, testable, and easier to maintain.
Reusability: Dependencies can be swapped out easily without modifying the core logic of a class, allowing for flexibility and reuse across different parts of your application.
Basic JavaScript DI Container
class DependencyInjectionContainer {
constructor() {
this.dependencies = {};
}
register(name, dependency) {
this.dependencies[name] = dependency;
}
resolve(name) {
return this.dependencies[name];
}
}
// Example Usage
class Database {
constructor() {
console.log("Database connected");
}
}
class UserService {
constructor(database) {
this.database = database;
}
getUserById(id) {
console.log(`Fetching user with ID ${id} using database:`, this.database);
}
}
const container = new DependencyInjectionContainer();
container.register('Database', Database); // Register the Database dependency
const userService = container.resolve('UserService');
userService.getUserById(1);
Explanation:
DependencyInjectionContainer
Class: This class acts as our DI container. It has adependencies
object to store registered dependencies by name.register(name, dependency)
Method: Used to add dependencies to the container. Thename
is used to identify the dependency later, anddependency
is the actual instance or constructor function of the class.resolve(name)
Method: Retrieves a registered dependency by its name. It returns the associated instance or function.Example Usage:
We define a
Database
class to represent database interactions (simplified).The
UserService
class depends on adatabase
. Instead of creating the database directly, it takes it as a parameter in its constructor.In the main part:
We create an instance of
DependencyInjectionContainer
.We register the
Database
class with the container usingcontainer.register('Database', Database)
.We resolve the
UserService
(which depends on theDatabase
), and it receives a database instance injected by the container.
Key Points:
Flexibility: You can easily change dependencies without modifying classes that use them.
Testability: It's much easier to test individual components when they receive their dependencies through injection, allowing you to control what they interact with during tests.
Last updated