Ответ
Service Locator (Локатор служб) — это паттерн проектирования, который предоставляет глобальный реестр для поиска и получения зависимостей (сервисов), скрывая детали их создания. Это альтернатива Dependency Injection (DI), где зависимости не "внедряются", а "запрашиваются" клиентом.
Базовая реализация на Swift:
class ServiceLocator {
static let shared = ServiceLocator()
private var services: [String: Any] = [:]
// Регистрация сервиса по его типу
func register<T>(_ service: T) {
let key = String(describing: T.self)
services[key] = service
}
// Разрешение (получение) сервиса по типу
func resolve<T>() -> T? {
let key = String(describing: T.self)
return services[key] as? T
}
}
// 1. Регистрация сервисов (обычно при запуске приложения)
ServiceLocator.shared.register(NetworkService())
ServiceLocator.shared.register(DatabaseService())
// 2. Использование в коде
class ViewModel {
// Зависимость неявно получена через локатор
private let networkService: NetworkService? = ServiceLocator.shared.resolve()
}
| Сравнение с Dependency Injection (DI): | Аспект | Service Locator | Dependency Injection (через конструктор) |
|---|---|---|---|
| Видимость зависимостей | Скрыты (класс сам их ищет) | Явные (передаются как параметры) | |
| Тестируемость | Сложнее, требует настройки локатора в тестах | Легче, зависимости можно передать как mock/stub | |
| Связность кода | Выше (класс знает о локаторе) | Ниже (класс знает только о своих интерфейсах) |
Недостатки (почему часто считается антипаттерном):
- Скрытые зависимости: Усложняет понимание того, от чего зависит класс.
- Усложняет тестирование: Требует конфигурации глобального состояния (
shared) для каждого теста. - Зависимость от глобального состояния: Противоречит принципам модульности и может привести к непредсказуемому поведению.