All 15 Design Patterns in Java questions
More in Design Patterns in Java
Advertisement
Back to results for “Dependency injection”
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?

Advanced

Answer

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 PaymentGateway
Real-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.

Common follow-ups: What's the difference between constructor injection, setter injection, and field injection, and why is constructor injection generally preferred?;At what codebase size/complexity does manual DI wiring typically become unwieldy enough to justify adopting a framework like Spring?