dependency-injection dependency injection - Инъекция зависимостей против заводского шаблона





13 Answers

Я бы предложил сохранить простые и простые понятия. Injection Dependency - это скорее архитектурный шаблон для слабосопряженных программных компонентов. Заводская модель - это всего лишь один способ отделить ответственность за создание объектов других классов для другого объекта. Фабричный шаблон можно назвать инструментом для реализации DI. Инъекция зависимостей может быть реализована многими способами, такими как DI, используя конструкторы, используя файлы сопоставления xml и т. Д.

.net русском внедрение

Большинство примеров, приведенных для использования Dependency Injection, мы также можем решить, используя заводскую модель. Похоже, когда дело доходит до использования / дизайна, разница между инъекцией зависимостей и фабрикой размыта или тонка.

Когда-то кто-то сказал мне, что это то, как вы его используете, что имеет значение!

Я однажды использовал StructureMap контейнер DI для решения проблемы, позже я переработал его для работы с простой фабрикой и удалил ссылки на StructureMap.

Может ли кто-нибудь сказать мне, в чем разница между ними и где использовать что, какая здесь лучшая практика?




Есть проблемы, которые легко решить с помощью инъекции зависимостей, которые не так легко решить с помощью набора фабрик.

Некоторая разница между, с одной стороны, инверсией управления и инъекцией зависимостей (IOC / DI), а с другой стороны, локатором сервисов или набором заводов (фабрики) является:

IOC / DI является полной экосистемой доменных объектов и услуг сама по себе. Он устанавливает все для вас так, как вы указываете. Объекты и службы домена создаются контейнером и не строят себя: поэтому они не имеют никаких зависимостей от контейнера или на каких-либо фабриках. IOC / DI обеспечивает чрезвычайно высокую степень конфигурирования, причем вся конфигурация в одном месте (конструкция контейнера) находится на самом верхнем слое вашего приложения (GUI, веб-интерфейс).

Factory абстрагирует некоторые из объектов вашего домена и услуг. Но объекты домена и службы по-прежнему несут ответственность за выяснение того, как построить себя и как получить все, от чего они зависят. Все эти «активные» зависимости фильтруют все слои в вашем приложении. Не существует единого места для настройки всего.




Одним из недостатков DI является то, что он не может инициализировать объекты с логикой. Например, когда мне нужно создать символ, у которого есть случайное имя и возраст, DI не является выбором по шаблону фабрики. С заводами мы можем легко инкапсулировать случайный алгоритм из создания объекта, который поддерживает один из шаблонов проектирования, называемый «Инкапсулировать, что меняется».




Я считаю, что DI - это тип слоя абстракции на фабриках, но они также обеспечивают преимущества за пределами абстракции. Настоящая фабрика знает, как создать экземпляр одного типа и настроить его. Хороший уровень DI предоставляет возможность посредством конфигурации создавать и настраивать многие типы.

Очевидно, что для проекта с несколькими простыми типами, который требует относительно стабильной бизнес-логики при их построении, фабричный шаблон прост для понимания, реализации и хорошо работает.

OTOH, если у вас есть проект, содержащий множество типов, реализация которых вы часто будете менять, DI дает вам гибкость благодаря своей конфигурации, чтобы сделать это во время выполнения без необходимости перекомпилировать ваши заводы.




теория

Необходимо рассмотреть два важных момента:

  1. Кто создает объекты

    • [Factory]: вам нужно написать объект HOW, который должен быть создан. У вас есть отдельный класс Factory, который содержит логику создания.
    • [Injection Dependency]: в практических случаях делаются внешние фреймворки (например, на Java, которые будут spring / ejb / guice). Инъекция происходит «магически» без эксплицитного создания новых объектов
  2. Какие объекты он управляет:

    • [Factory]: обычно отвечает за создание объектов с сохранением состояния
    • [Инъекции зависимостей] Более вероятно создание объектов без гражданства

Практический пример использования как заводской, так и зависимой инъекции в одном проекте

  1. Что мы хотим построить

Модуль приложения для создания порядка, который содержит несколько записей, называемых orderline.

  1. Архитектура

Предположим, мы хотим создать следующую архитектуру слоя:

Объектами домена могут быть объекты, хранящиеся внутри базы данных. Репозиторий (DAO) помогает с извлечением объектов из базы данных. Служба предоставляет API для других модулей. Аловы для операций над модулем order

  1. Уровень домена и использование заводов

Объектами, которые будут в базе данных, являются Order and OrderLine. Заказ может иметь несколько OrderLines.

Теперь идет важная часть дизайна. Должны ли модули за пределами этого создавать и управлять OrderLines самостоятельно? Нет. Строка заказа должна существовать только в том случае, если у вас есть связанный с ним заказ. Было бы лучше, если бы вы могли скрывать внутреннюю реализацию внешних классов.

Но как создать заказ без знания о OrderLines?

завод

Тот, кто хочет создать новый заказ, использовал OrderFactory (который скроет подробности о том, как мы создаем Order).

Вот как он будет выглядеть внутри IDE. Классы вне пакета domain будут использовать OrderFactory вместо конструктора внутри Order

  1. Инъекционная инъекция зависимостей Инъекция более часто используется с не имеющими аналогов слоями, такими как репозиторий и служба.

OrderRepository и OrderService управляются инфраструктурой внедрения зависимостей. Репозиторий отвечает за управление операциями CRUD в базе данных. Служба внедряет репозиторий и использует его для сохранения / поиска правильных классов домена.




При инъекции зависимостей клиенту не нужно самостоятельно получать свои зависимости, а все готово заранее.

С заводами кто-то должен их вызвать, чтобы получить сгенерированные объекты до того места, где они необходимы.

Разница заключается в основном в этой одной строке, где выполняется вызов фабрики и выборка построенного объекта.

Но с заводами вы должны написать эту 1 строку везде, где вам нужен такой объект. С DI вам просто нужно создать проводку (связь между использованием и созданным объектом) один раз и просто опираться на присутствие объекта после этого повсюду. С другой стороны, DI часто требует немного больше (сколько зависит от структуры) работы на стороне подготовки.




Вы можете взглянуть на эту ссылку для сравнения двух (и других) подходов в реальном примере.

В основном, когда требования меняются, вы в конечном итоге модифицируете больше кода, если вместо DI используются фабрики.

Это также относится к ручному DI (т. Е. Когда нет внешней структуры, которая обеспечивает зависимости к вашим объектам, но вы передаете их в каждом конструкторе).




Binoj,

Я не думаю, что вам нужно выбирать один за другим.

Действие перемещения зависимого класса или интерфейса на конструктор или сеттер классов следует за шаблоном DI. Объект, который вы передаете конструктору или набору, может быть реализован с помощью Factory.

Когда использовать? Используйте шаблон или шаблоны, которые находятся в рулевой рубке разработчика. Что они чувствуют себя наиболее комфортно и легче всего понять.




Мои мысли:

Dependecy Injection: передать коллабораторы в качестве параметров для конструкторов. Dependency Injection Framework: универсальная и настраиваемая фабрика для создания объектов, передаваемых в качестве параметров конструкторам.




Заводская модель

Модель проектирования завода характеризуется

  • Интерфейс
  • Классы реализации
  • Завод

Вы можете наблюдать несколько вещей, когда задаетесь вопросом, как ниже

  • Когда фабрика создаст объект для классов реализации - время выполнения или время компиляции?
  • Что делать, если вы хотите переключить реализацию во время выполнения? - Невозможно

Они обрабатываются инъекцией зависимостей.

Внедрение зависимости

У вас могут быть разные способы, с помощью которых вы можете вводить зависимость. Для простоты можно перейти с интерфейсом Injection

В DI контейнер создает необходимые экземпляры и «внедряет» их в объект.

Таким образом, исключается статический экземпляр.

Пример:

public class MyClass{

  MyInterface find= null;

  //Constructor- During the object instantiation

  public MyClass(MyInterface myInterface ) {

       find = myInterface ;
  }

  public void myMethod(){

       find.doSomething();

  }
}



Большинство ответов здесь объясняют концептуальную разницу и детали реализации обоих. Однако мне не удалось найти объяснения о различиях в применении, которые ИМО является самым важным и об этом спрашивает ОП. Поэтому позвольте мне снова открыть эту тему ...

Когда-то кто-то сказал мне, что это то, как вы его используете, что имеет значение!

Именно так. В 90% случаях вы можете получить ссылку на объект, используя Factory или DI, и обычно вы заканчиваете последним. В других 10% случаях использование Factory является правильным . Эти случаи включают в себя получение объектов по переменной во временных параметрах. Как это:

IWebClient client = factoryWithCache.GetWebClient(url: ".com",
        useCookies: false, connectionTimeout: 120);

В этом случае получение client из DI невозможно (или, по крайней мере, требует некоторого уродливого обходного пути). Так как общее правило для принятия решения: если зависимость может быть получена без каких-либо вычисляемых параметров времени выполнения, тогда DI является предпочтительным, иначе используйте Factory.




Говоря простыми словами, метод Injection vs Factory подразумевает механизм push vs pull соответственно.

С механизмом pull: класс косвенно зависит от метода Factory, который, в свою очередь, зависит от конкретных классов.

Механизм Push: компонент корня может быть сконфигурирован со всеми зависимыми компонентами в одном месте и, таким образом, способствует высокому обслуживанию и ослаблению сцепления.

С ответственностью Factory method по-прежнему лежит класс (хотя и косвенно) для создания нового объекта, где, как и в случае инъекции зависимостей, ответственность за аутсорсинг (за счет утечки абстракции)




Я использую оба для создания стратегии инверсии управления с большей удобочитаемостью для разработчиков, которым нужно поддерживать их после меня.

Я использую Factory для создания разных объектов Layer (Business, Data Access).

ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness();

Другой разработчик увидит это и при создании объекта Business Layer он будет выглядеть в BusinessFactory, а Intellisense предоставит разработчику все возможные бизнес-слои для создания. Не нужно играть в игру, найти интерфейс, который я хочу создать.

Эта структура уже является инверсией управления. Я больше не несу ответственность за создание конкретного объекта. Но вам все равно нужно обеспечить, чтобы Injection Dependency могла легко изменять ситуацию. Создание собственного пользовательского Injection Dependency смешно, поэтому я использую Unity. Внутри CreateCarBusiness () я прошу Unity разрешить, какой класс принадлежит этому, и его продолжительность жизни.

Таким образом, мой код Factory Dependency Injection:

public static class BusinessFactory
{
    public static ICarBusiness CreateCarBusiness()
    {
       return Container.Resolve<ICarBusiness>();
    }
}

Теперь у меня есть преимущество обоих. Мой код также более читабельен для других разработчиков в отношении областей моих объектов, которые я использую, вместо Constructor Dependency Injection, которые просто говорят, что каждый объект доступен, когда класс создан.

Я использую это, чтобы изменить свой доступ к данным базы данных на пользовательский кодированный уровень доступа к данным при создании модульных тестов. Я не хочу, чтобы мои модульные тесты связывались с базами данных, веб-серверами, серверами электронной почты и т. Д. Им нужно протестировать мой бизнес-уровень, потому что это интеллект.




Related