Java › Design Patterns in Java
How would you implement the Dependency Injection pattern manually (without a framework like Spring) using constructor injection, and what testability benefits does this provide?
AdvancedAnswer
Manual constructor-based dependency injection means a class declares its dependencies as constructor parameters (rather than instantiating them directly inside the class or looking them up from a global registry/service locator), with the responsibility of actually providing those dependencies pushed to the caller (or, in a larger application, to a small "composition root" that wires everything together near the application's entry point) -- this decouples a class from concrete implementations of its dependencies, letting tests substitute mock/stub implementations trivially by passing them directly into the constructor, without needing any framework, reflection, or special test configuration.
public interface PaymentGateway { boolean charge(double amount); }
public class OrderService {
private final PaymentGateway gateway;
public OrderService(PaymentGateway gateway) { // dependency injected via constructor
this.gateway = gateway;
}
public boolean placeOrder(double total) { return gateway.charge(total); }
}
// In tests, trivially substitute a fake implementation, no framework needed
OrderService testService = new OrderService(amount -> true); // lambda implementing PaymentGatewayReal-world example A unit test for OrderService constructs it directly with a hand-written fake PaymentGateway lambda that always returns true, testing OrderService's own logic in complete isolation from any real payment processing code or network calls, entirely without needing a DI framework or mocking library for this simple case.