![]() |
VOOZH | about |
Dependency Injection (DI) is a design pattern where an object receives its dependencies from an external source instead of creating them itself. It separates dependency creation from usage, improving flexibility, testability, and maintainability.
Example:
Carclass might depend on aEngineclass to run. Without DI, theCarclass would directly create or manage theEngineinstance within its code, which makes the two classes tightly coupled. This approach can create problems, particularly when you need to test, extend, or modify the classes in the future.
Engine ones in the Car example) into the class from an external source, rather than having the class create them. In Dependency Injection, the dependencies of a class are injected from the outside, rather than the class creating or managing its dependencies internally. This pattern has four main roles:
The client is the class or component that depends on a service to perform its operations.
The service is the class or component that provides specific functionality needed by the client.
The injector is responsible for creating service instances and supplying them to the client.
The interface defines a contract that specifies what methods a service must implement.
Dependency Injection is widely used to build flexible, maintainable, and loosely coupled applications.
Imagine you're building an application that sends notifications to users. You want to make the notification system flexible so you can change the notification provider (email, SMS, push notifications, etc.) without modifying the core application logic.
Issues:
NotificationService is tightly coupled to the EmailProvider, making it difficult to switch to a different provider without code changes.NotificationService in isolation is challenging as it directly uses EmailProvider.Sending Email to abc@example.com: Hello via Email! Sending SMS to 123-456-7890: Hello via SMS!
Benefits of using Dependency Injection Design Pattern in this solution above:
NotificationService no longer depends on a specific implementation, making it adaptable to different providers.NotificationService in isolation.There are mainly three types of dependency injection, that are Constructor Injection, Setter Injection and Interface Injection. Let's understand these three approaches to dependency injection using an example with the implementation.
You are building a Vehicle Management System for a car rental service. The system needs to manage cars and their engines. Each car should have an engine type and the system should ensure that the car has all necessary components when it's instantiated.
With Constructor Injection, dependencies are provided to a class through its constructor when the object is created. This is the most common form of DI because it makes dependencies clear, mandatory, and immutable after the object is constructed.
Engine started Car is driving
Setter Injection involves providing the dependency via a setter method after the object is created. This approach is more flexible than constructor injection because it allows dependencies to be set or changed after object creation.
Engine started Car is driving
Interface Injection requires the class to implement an interface that provides a method for receiving the dependency. This is less commonly used in Java, but it allows for more flexibility and decoupling.
Engine started Car is driving
Dependency Injection improves flexibility, maintainability, and testability by reducing direct dependencies between components.
Although Dependency Injection (DI) improves flexibility and maintainability, it also has some limitations in certain scenarios.