Dependency Injection (DI) is a software design pattern that promotes loose coupling between classes by passing dependencies (objects that a class needs to function) into the class rather than having the class create them itself. This makes code more modular, testable, and maintainable.
Here's a simplified example of how DI works:
1. Interface for the Dependency:
interface Engine {
void start();
}
2. Concrete Implementations of the Dependency:
class WorkingEngine implements Engine {
@Override
public void start() {
System.out.println("Engine started successfully.");
}
}
class BrokenEngine implements Engine {
@Override
public void start() {
throw new RuntimeException("Engine is broken.");
}
}
3. The Class Using the Dependency:
class Car {
private final Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void start() {
engine.start();
}
}
4. Test Cases:
import org.junit.jupiter.api.Test;
public class CarTest {
@Test
public void carStartsWithWorkingEngine() {
Engine workingEngine = new WorkingEngine();
Car car = new Car(workingEngine);
car.start();
// Assert that the car started successfully
}
@Test
public void carThrowsExceptionWithBrokenEngine() {
Engine brokenEngine = new BrokenEngine();
Car car = new Car(brokenEngine);
assertThrows(RuntimeException.class, () -> car.start());
}
}
Explanation:
- Interface: The
Engineinterface defines the contract for the dependency, allowing for different implementations. - Concrete Implementations: The
WorkingEngineandBrokenEngineclasses implement theEngineinterface, providing different behaviors. - Dependency Injection: The
Carclass takes anEngineinstance as a constructor parameter, injecting the dependency. - Test Cases: The
CarTestthe class demonstrates how to test theCarclass with differentEngineimplementations, ensuring its correctness under various conditions.
Key Points:
- Loose Coupling: The
Carclass is decoupled from specificEngineimplementations, promoting flexibility and maintainability. - Testability: The ability to inject different
Engineinstances makes testing easier and more thorough. - Readability: The code is well-structured and easy to understand, with a clear separation of concerns.
- Error Handling: The
BrokenEngineclass demonstrates how to handle potential exceptions in the dependency.
This example effectively illustrates the principles of Dependency Injection and its benefits in building robust and testable Java applications.
No comments:
Post a Comment