# Service Locator
The **Service Locator** is a design pattern in which a class obtains its dependencies by *asking* a central registry for them, rather than having them passed in. Instead of `constructor(db: Database)`, the class does `this.db = ServiceLocator.get<Database>()`. The locator holds a map of service-type → instance and hands them out on request.
It's one way to implement [[Inversion of Control (IoC)]] — the locator owns construction and lifetime — and one way to satisfy the [[Dependency Inversion Principle (DIP)]] when the locator returns abstractions. But it's widely considered an *antipattern* in modern code, especially compared to [[Dependency Injection (DI)]].
## Mechanism
A `ServiceLocator` is a global (or near-global) registry. At application startup, services are registered: `ServiceLocator.register(Database, new PostgresClient(...))`. Anywhere in the codebase, code can call `ServiceLocator.get(Database)` and receive the instance. The locator may be a static class, a singleton, or a thread-local context.
```
Class A ──asks──> ServiceLocator ──hands back──> Database instance
```
Compare with constructor DI:
```
Composition Root ──constructs and passes──> Class A(database)
```
Same goal — A doesn't `new` its own database — but radically different visibility properties.
## Why it's tempting
- **No wiring at the call site**: any class anywhere can grab any service without plumbing dependencies through constructors.
- **Refactoring-light**: adding a new dependency to a deep class doesn't require updating every caller.
- **Familiar in some ecosystems**: legacy J2EE (`InitialContext` JNDI lookups), older Spring code, classic ASP.NET (`HttpContext.Current`), Unity game engine.
## Why it's a problem
- **Hidden dependencies**: a class's *true* dependencies aren't visible from its constructor or signature. Reading a class no longer tells you what it needs to function. [[Mark Seemann]] calls Service Locator an antipattern primarily for this reason.
- **Hostile to testing**: tests must configure the global locator before exercising the class, then tear it down. Parallel tests fight over shared state. Mocks bleed across test boundaries.
- **Runtime failures instead of compile-time**: missing registrations explode at first use, not at startup. Some locators don't even fail loudly — they return `null`.
- **Coupling to the locator itself**: every class that uses the pattern depends on the locator class, not just on its actual collaborators.
- **Encourages God-objects**: it's frictionless to add "just one more" dependency, so classes grow until they pull in half the system.
## When it might be acceptable
- **Framework boundary code** where the framework constructs your object and you genuinely cannot influence its constructor (e.g., legacy Servlet API, some plugin SPIs).
- **Plugin / extension discovery** where the set of services is dynamic and unknown at compile time.
- **Lightweight scripts** where the test/lifecycle costs are negligible.
In all other cases, prefer constructor [[Dependency Injection (DI)]] from a [[Composition Root]].
## Service Locator vs DI
| | Service Locator | Dependency Injection |
|---|---|---|
| **Direction** | Class *pulls* its dependencies | Dependencies *pushed* into the class |
| **Visibility** | Hidden inside method bodies | Explicit in constructor / setter |
| **Test setup** | Configure global registry | Pass test doubles directly |
| **Failure mode** | Runtime, on first use | Compile-time or composition-root startup |
| **Coupling** | Class → Locator → Service | Class → Service abstraction only |
## References
- Martin Fowler — *Inversion of Control Containers and the Dependency Injection pattern* (2004) — https://martinfowler.com/articles/injection.html (compares Service Locator and DI explicitly)
- Mark Seemann — *Service Locator is an Anti-Pattern* (2010) — https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/
## Related
- [[Dependency Injection (DI)]]
- [[Inversion of Control (IoC)]]
- [[Dependency Inversion Principle (DIP)]]
- [[Composition Root]]
- [[Loose Coupling]]
- [[SOLID Principles]]
- [[Mark Seemann]]
- [[Martin Fowler]]