← Назад к вопросам

В чем различия Service Locator и Dependency Injection?

2.0 Middle🔥 131 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Краткое резюме

Service Locator и Dependency Injection — это два паттерна управления зависимостями. Service Locator — это объект, который хранит и предоставляет экземпляры сервисов по требованию. Dependency Injection передаёт зависимости в конструктор или через методы. Несмотря на похожесть, они имеют принципиальные различия в архитектуре и тестируемости.

Service Locator

Service Locator — это паттерн, где централизованный объект управляет всеми зависимостями и предоставляет их компонентам по запросу.

Пример реализации

class ServiceLocator:
    _services = {}
    
    @classmethod
    def register(cls, name: str, service):
        cls._services[name] = service
    
    @classmethod
    def get(cls, name: str):
        if name not in cls._services:
            raise ValueError(f"Service {name} not found")
        return cls._services[name]

# Регистрация сервисов
locator = ServiceLocator()
locator.register("database", Database())
locator.register("logger", Logger())

# Использование в компоненте
class UserRepository:
    def __init__(self):
        self.db = ServiceLocator.get("database")
        self.logger = ServiceLocator.get("logger")

Характеристики

  • Компонент самостоятельно ищет нужные зависимости
  • Глобальное состояние (слабое место)
  • Простая реализация для небольших проектов
  • Скрытые зависимости (не видно из сигнатуры класса)

Dependency Injection

Dependency Injection передаёт зависимости извне, обычно через конструктор (Constructor Injection), метод (Setter Injection) или параметр функции.

Пример конструктора (Constructor Injection)

class UserRepository:
    def __init__(self, db: Database, logger: Logger):
        self.db = db
        self.logger = logger

# Использование
database = Database()
logger = Logger()
repo = UserRepository(database, logger)

Пример Setter Injection

class UserRepository:
    def __init__(self):
        self.db = None
        self.logger = None
    
    def set_database(self, db: Database):
        self.db = db
        return self
    
    def set_logger(self, logger: Logger):
        self.logger = logger
        return self

# Использование
repo = UserRepository()
repo.set_database(Database()).set_logger(Logger())

Сравнительная таблица

АспектService LocatorDependency Injection
Источник зависимостиКомпонент сам ищетПередаётся извне
Видимость зависимостейСкрытые (в коде)Явные (в сигнатуре)
ТестируемостьСложнее (нужно мокировать глобальный объект)Проще (подставляешь mock в конструктор)
СвязанностьВысокая (привязка к locator)Низкая (только интерфейсы)
ПроизводительностьПоиск во время выполненияЗнаем зависимости заранее

Почему DI лучше Service Locator

1. Явные зависимости

# Service Locator — скрытые зависимости
class PaymentProcessor:
    def process(self):
        db = ServiceLocator.get("database")  # Откуда это берётся?
        logger = ServiceLocator.get("logger")

# DI — явные зависимости
class PaymentProcessor:
    def __init__(self, db: Database, logger: Logger):
        self.db = db
        self.logger = logger

2. Тестируемость

# DI — просто передаём mock
class TestPaymentProcessor:
    def test_process(self):
        mock_db = MockDatabase()
        mock_logger = MockLogger()
        processor = PaymentProcessor(mock_db, mock_logger)
        result = processor.process()
        assert result.success

Практический пример

from typing import Protocol

class DatabasePort(Protocol):
    def execute(self, query: str): ...

class UserService:
    def __init__(self, db: DatabasePort):
        self.db = db
    
    def create_user(self, name: str) -> dict:
        return self.db.execute(f"INSERT INTO users VALUES ({name})")

Заключение

DI — это современный стандарт, поддерживаемый всеми серьёзными фреймворками (FastAPI, Django). Service Locator — это anti-pattern. Используй DI для явности, тестируемости и масштабируемости.

В чем различия Service Locator и Dependency Injection? | PrepBro