Service Locator
Problem
Passing shared services like analytics, logging, or feature flags through every component creates deep prop chains. Components become tightly coupled to specific service implementations. Changing how services are created or configured requires touching dozens of files across the codebase.
Solution
Provide a central registry where components can look up dependencies rather than having them injected. This simplifies setup but can obscure dependencies and make testing harder.
Example
This demonstrates a centralized service registry that allows components to look up shared services without prop drilling, simplifying component interfaces but creating implicit dependencies.
// Centralized registry of shared services
const services = {
api: new ApiService(),
auth: new AuthService(),
logger: new LoggerService()
};
// Lookup function to access services
function getService(name) {
return services[name];
}
// Components can access services without prop drilling
const api = getService('api');
Benefits
- Eliminates deep prop drilling for shared services.
- Provides single point to configure and swap service implementations.
- Simplifies component interfaces by removing service dependencies from props.
- Makes it easy to access services from anywhere in the application.
Tradeoffs
- Hides dependencies, making them implicit rather than explicit.
- Makes testing harder since dependencies aren’t injected.
- Creates global coupling to the service locator.
- Can lead to service explosion if not carefully managed.