Dependency Inversion Principle (DIP) — это архитектурный принцип, согласно которому:
Это означает, что бизнес-логика (например, сервис работы с заказами) не должен знать и напрямую использовать конкретную реализацию инфраструктуры (например, класс, реализующий почтовую отправку), а работать через абстракцию (интерфейс), которую внедряешь через механизм DI-контейнера или вручную.
Пример кода на C#:
public interface IEmailSender { void Send(string to, string message); } public class SmtpEmailSender : IEmailSender { public void Send(string to, string message) { // Реализация отправки email } } public class OrderService { private readonly IEmailSender _emailSender; public OrderService(IEmailSender emailSender) { _emailSender = emailSender; } public void PlaceOrder(string customer) { // бизнес-логика _emailSender.Send(customer, "Your order is placed!"); } }
Ключевые особенности:
DIP — это просто внедрение зависимостей через конструктор?
Нет. DIP — это про отделение абстракций от реализаций. Внедрение зависимостей (Dependency Injection, DI) — это лишь инструмент, с помощью которого реализуется DIP. DIP можно реализовать и без DI-контейнера, вручную обеспечив разделение абстракций и деталей.
Если у вас одна реализация интерфейса, обязателен ли DIP?
Да, принцип все равно применим, если возможно расширение. Ввод абстракций готовит систему к изменению требований без модификации кода высокого уровня. Даже с одной реализацией интерфейса, слабая связанность облегчает тестирование и развитие системы.
Можно ли нарушить DIP, используя логику в фабриках или сервис-локаторах?
Да. Если фабрика или сервис-локатор знает о деталях реализации и динамически связывает их без использования интерфейса на клиентской стороне, DIP нарушается, несмотря на внешнее наличие абстракций.