Ответ
Dependency Injection (DI, Внедрение зависимостей) — это паттерн проектирования, при котором зависимости объекта (сервисы, которые он использует) передаются ему извне, а не создаются внутри самого объекта. Это делает код более гибким, тестируемым и слабосвязанным.
Основные способы внедрения:
- Через конструктор (наиболее предпочтительный): Зависимости передаются при создании объекта.
- Через сеттер: Зависимости устанавливаются после создания объекта.
- Через интерфейс: Объект реализует интерфейс, через который ему передаются зависимости.
Пример на Python (внедрение через конструктор):
# Сервис (зависимость)
class EmailService:
def send(self, message, recipient):
print(f"Sending '{message}' to {recipient}")
# Логика отправки email
# Класс, который зависит от EmailService
class NotificationManager:
def __init__(self, email_service: EmailService): # Зависимость внедряется здесь
self._email_service = email_service
def notify_user(self, user_email, message):
self._email_service.send(message, user_email)
# Использование и преимущества для тестирования
# 1. Реальное использование:
real_email_service = EmailService()
notifier = NotificationManager(real_email_service)
notifier.notify_user("user@example.com", "Welcome!")
# 2. Легкое тестирование с mock-объектом:
from unittest.mock import Mock
def test_notification_manager():
mock_email_service = Mock(spec=EmailService)
manager = NotificationManager(mock_email_service)
manager.notify_user("test@example.com", "Test message")
# Проверяем, что зависимость была вызвана корректно
mock_email_service.send.assert_called_once_with("Test message", "test@example.com")
Ключевые преимущества DI:
- Упрощение тестирования: Реальные зависимости легко подменить заглушками (mocks/stubs).
- Снижение связанности: Классы не зависят от конкретных реализаций, а только от абстракций (интерфейсов).
- Повторное использование кода: Компоненты становятся более независимыми.
- Гибкость конфигурации: Поведение приложения можно менять, конфигурируя набор внедряемых зависимостей.