100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

Dependency Injection vs Service Locator

Dependency injection vs the service locator pattern: visibility, testability trade-offs, and Java examples for interview prep.

hardQ80 of 226 in Object Oriented Programming Est. time: 6 minsLast updated:
Open Code Lab

Expected Interview Answer

Dependency injection has an external party push required collaborators into an object, typically via its constructor, so dependencies appear explicitly in the type’s API; the service locator pattern instead has the object actively pull dependencies at runtime by asking a central registry for them, hiding those dependencies inside the method body.

With dependency injection, a class’s constructor or setter signature documents exactly what it needs, so a reviewer or test author can see and supply every dependency without reading the implementation, and a compiler or container can verify at wiring time that everything is satisfiable. With a service locator, code calls something like ServiceLocator.get(PaymentGateway.class) inside a method, so the dependency is invisible from the public API and only surfaces as a runtime failure if it is missing from the registry. Both patterns invert control away from the object constructing its own dependencies directly, but service locator still couples every consuming class to the locator itself, whereas DI containers keep consuming classes free of any framework reference. This is why most modern architectural guidance, including Martin Fowler’s well-known writing on the topic, favors dependency injection over service locator for testability and API clarity, even though service locator can be simpler to introduce into legacy code incrementally.

  • Dependency injection makes required collaborators visible in the API
  • DI enables compile/wiring-time verification of completeness
  • Service locator can be simpler to retrofit into existing code
  • DI avoids coupling every class to a lookup mechanism

AI Mentor Explanation

A captain who receives the pre-selected playing eleven handed directly to them by the selection committee before the toss experiences dependency injection: the players are visibly assigned up front. A captain who instead has to walk to a central equipment shed mid-match and request “give me a spare bowler” whenever a need arises experiences the service locator pattern: the dependency is hidden until the moment it is actively requested, and only then does anyone discover whether it is available.

Step-by-Step Explanation

  1. Step 1

    Declare dependencies explicitly (DI)

    List required collaborators as constructor or setter parameters, visible in the public API.

  2. Step 2

    Let the container supply them (DI)

    An external container or test resolves and injects those declared dependencies.

  3. Step 3

    Contrast with a locator lookup (Service Locator)

    Code instead calls a registry, e.g. ServiceLocator.get(X.class), inside a method body to fetch a dependency.

  4. Step 4

    Weigh visibility and testability

    DI exposes needs in signatures and fails fast at wiring time; service locator hides needs and can fail late at runtime.

What Interviewer Expects

  • A precise contrast: push (DI) vs pull (service locator)
  • Awareness that both patterns invert control away from direct instantiation
  • A clear statement of the testability/API-clarity trade-off
  • Reference to why most modern guidance favors DI over service locator

Common Mistakes

  • Claiming service locator and dependency injection are the same pattern
  • Not recognizing that service locator still couples classes to the locator itself
  • Assuming service locator has no valid use cases at all
  • Failing to mention that DI dependencies are visible in the API while service locator hides them

Best Answer (HR Friendly)

With dependency injection, an object is handed everything it needs up front, so you can see exactly what it depends on just by reading its constructor. With a service locator, the object instead reaches out to a central registry whenever it needs something, so the dependency is buried inside the method logic and only shows up as a problem if it is missing at runtime. I generally prefer dependency injection because it keeps dependencies visible and makes testing much easier.

Code Example

Dependency injection vs service locator side by side
// Dependency Injection: dependency is visible in the constructor
class OrderServiceDI {
    private final PaymentGateway gateway;

    OrderServiceDI(PaymentGateway gateway) {
        this.gateway = gateway; // required, explicit, testable
    }

    void checkout(double amount) {
        gateway.charge(amount);
    }
}

// Service Locator: dependency is hidden inside the method
class OrderServiceLocator {
    void checkout(double amount) {
        PaymentGateway gateway =
            ServiceLocator.get(PaymentGateway.class); // hidden lookup
        gateway.charge(amount);
    }
}

Follow-up Questions

  • Why does Martin Fowler argue dependency injection is generally preferable to service locator?
  • Does the service locator pattern still count as inversion of control?
  • How does unit testing differ between the two approaches?
  • When might a service locator still be a reasonable choice?

MCQ Practice

1. In dependency injection, dependencies are?

DI makes required dependencies part of the public constructor/setter API, visible without reading the implementation.

2. A key drawback of the service locator pattern is?

Because the lookup happens inside method bodies, missing dependencies surface only as runtime errors, not compile/wiring-time ones.

3. What do dependency injection and service locator have in common?

Both patterns move dependency resolution out of the consuming class, though they differ in how visible that dependency is.

Flash Cards

DI vs service locator, one line?DI pushes dependencies in via visible constructor/setter parameters; service locator has the object pull them from a registry.

Which pattern is more testable, and why?Dependency injection, because required collaborators are explicit and can be substituted directly without a registry.

What do both patterns share?Both invert control away from a class directly instantiating its own dependencies.

Main criticism of service locator?It hides dependencies inside method bodies and couples every consumer to the locator itself.

1 / 4

Continue Learning