Большинство примеров, приведенных для использования Dependency Injection, мы также можем решить, используя фабричный шаблон. Похоже, что когда дело доходит до использования / дизайна, разница между внедрением зависимости и фабрикой размыта или тонка.
Однажды кто-то сказал мне, что то, как вы используете это, имеет значение!
Однажды я использовал StructureMap DI-контейнер для решения проблемы, позже я переработал его для работы с простой фабрикой и удалил ссылки на StructureMap.
Может кто-нибудь сказать мне, в чем разница между ними и где что использовать, какова лучшая практика здесь?
dependency-injection
factory-pattern
design-patterns
Binoj Antony
источник
источник
Ответы:
При использовании фабрики ваш код по-прежнему фактически отвечает за создание объектов. Используя DI, вы передаете эту ответственность другому классу или фреймворку, который отделен от вашего кода.
источник
Manually-Injected Dependency
Я бы предложил сохранить понятия простыми и понятными. Внедрение зависимостей - это скорее архитектурный шаблон для слабой связи программных компонентов. Фабричный шаблон - это всего лишь один из способов разделения ответственности за создание объектов других классов на другую сущность. Фабричный шаблон можно назвать инструментом для реализации DI. Внедрение зависимостей может быть реализовано многими способами, такими как DI с использованием конструкторов, с помощью сопоставления XML-файлов и т. Д.
источник
Внедрение зависимости
Вместо того, чтобы создавать экземпляры самих деталей, автомобиль запрашивает детали, необходимые для работы.
завод
Собирает кусочки вместе, чтобы создать законченный объект, и скрывает конкретный тип от звонящего.
Результат
Как видите, фабрики и DI дополняют друг друга.
Вы помните златовласку и трех медведей? Ну, инъекция зависимостей вроде этого. Вот три способа сделать то же самое.
Пример № 1 - Это худший вариант, потому что он полностью скрывает зависимость. Если бы вы смотрели на этот метод как на черный ящик, вы бы не поняли, что для этого нужна машина.
Пример № 2 - Это немного лучше, потому что теперь мы знаем, что нам нужна машина, поскольку мы проходим на автомобильном заводе. Но на этот раз мы проходим слишком много, так как все, что нужно на самом деле, - это машина. Мы проезжаем по фабрике только для того, чтобы построить машину, когда машина может быть построена вне метода и передана внутрь.
Пример № 3 - Это идеально, потому что метод запрашивает именно то , что ему нужно. Не слишком много или слишком мало. Мне не нужно писать MockCarFactory только для создания MockCars, я могу передать макет прямо. Он прямой и интерфейс не лжет.
Этот Google Tech Talk от Misko Hevery удивителен и является основой того, из чего я получил свой пример. http://www.youtube.com/watch?v=XcT4yYu_TTs
источник
Причина внедрения Dependency Injection (DI) и Factory Patterns заключается в том, что они являются двумя реализациями Inversion of Control (IoC), являющейся архитектурой программного обеспечения. Проще говоря, это два решения одной и той же проблемы.
Таким образом, чтобы ответить на вопрос, основное различие между шаблоном Factory и DI заключается в том, как получается ссылка на объект. С внедрением зависимости, как следует из названия, ссылка вводится или дается вашему коду. С шаблоном Factory ваш код должен запрашивать ссылку, чтобы ваш код выбирал объект. Обе реализации удаляют или разъединяют связь между кодом и базовым классом или тип ссылки на объект, используемый кодом.
Стоит отметить, что шаблоны Factory (или даже шаблоны Abstract Factory, которые являются фабриками, которые возвращают новые фабрики, которые возвращают ссылки на объекты) могут быть написаны для динамического выбора или ссылки на тип или класс объекта, запрашиваемого во время выполнения. Это делает их очень похожими (даже в большей степени, чем DI) на шаблон Service Locator, который является еще одной реализацией IoC.
Шаблон проектирования фабрики довольно стар (с точки зрения программного обеспечения) и существует уже некоторое время. С недавней популярности архитектурного шаблона IoC он возрождается.
Я предполагаю, что когда дело доходит до шаблонов проектирования IoC: инжекторы будут впрыскивать, локаторы будут размещаться, а заводы будут реорганизованы.
источник
Есть проблемы, которые легко решить с помощью внедрения зависимостей, которые не так легко решить с помощью набора фабрик.
Некоторое различие между, с одной стороны, инверсией управления и внедрением зависимостей (IOC / DI) и, с другой стороны, сервисным локатором или набором фабрик (фабрика), заключается в:
IOC / DI - это полноценная экосистема доменных объектов и сервисов сама по себе. Он настраивает все для вас так, как вы указываете. Ваши доменные объекты и сервисы создаются контейнером, а не сами по себе: поэтому у них нет зависимостей от контейнера или каких-либо фабрик. IOC / DI обеспечивает чрезвычайно высокую степень конфигурируемости, при этом вся конфигурация находится в одном месте (конструкция контейнера) на самом верхнем уровне вашего приложения (GUI, веб-интерфейс).
Фабрика абстрагируется от некоторых ваших доменных объектов и сервисов. Но доменные объекты и сервисы по-прежнему отвечают за выяснение того, как создать себя и как получить все, от чего они зависят. Все эти «активные» зависимости фильтруют все слои вашего приложения. Там нет единого места, чтобы пойти, чтобы настроить все.
источник
Одним из недостатков DI является то, что он не может инициализировать объекты с помощью логики. Например, когда мне нужно создать персонажа со случайным именем и возрастом, DI не является выбором по сравнению с фабричным шаблоном. С фабриками мы можем легко инкапсулировать случайный алгоритм от создания объекта, который поддерживает один из шаблонов проектирования, который называется «Инкапсуляция того, что меняется».
источник
От: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html
источник
Я полагаю, что DI - это тип уровня абстракции на фабриках, но они также предоставляют преимущества помимо абстракции. Настоящая фабрика знает, как создать один тип и настроить его. Хороший уровень DI предоставляет возможность посредством конфигурации создавать экземпляры и настраивать многие типы.
Очевидно, что для проекта с несколькими простыми типами, которые требуют относительно стабильной бизнес-логики в своей конструкции, фабричный шаблон прост для понимания, реализации и хорошо работает.
OTOH, если у вас есть проект, содержащий множество типов, чьи реализации вы ожидаете часто менять, DI дает вам гибкость благодаря его конфигурации для выполнения этого во время выполнения без перекомпиляции ваших фабрик.
источник
теория
Есть два важных момента для рассмотрения:
Кто создает объекты
Какими объектами он управляет:
Практический пример использования фабричной и зависимой инъекций в одном проекте
Модуль приложения для создания заказа, который содержит несколько записей, называемых строкой заказа.
Давайте предположим, что мы хотим создать следующую архитектуру слоя:
Доменные объекты могут быть объектами, хранящимися в базе данных. Репозиторий (DAO) помогает с извлечением объектов из базы данных. Сервис предоставляет API для других модулей. Допускает операции на
order
модулеОбъектами, которые будут в базе данных, являются Order и OrderLine. Заказ может иметь несколько строк заказа.
Теперь важная часть дизайна. Должны ли модули за пределами этого создавать и управлять OrderLines самостоятельно? Нет. Строка заказа должна существовать только тогда, когда с ней связан Заказ. Было бы лучше, если бы вы могли скрыть внутреннюю реализацию от внешних классов.
Но как создать Order без знания OrderLines?
завод
Кто-то, кто хочет создать новый заказ, использовал OrderFactory (который скрывает подробности о том, как мы создаем заказ).
Вот как это будет выглядеть внутри IDE. Классы вне
domain
пакета будут использоватьOrderFactory
вместо конструктора внутриOrder
OrderRepository и OrderService управляются структурой внедрения зависимостей. Репозиторий отвечает за управление операциями CRUD над базой данных. Сервис внедряет репозиторий и использует его для сохранения / поиска правильных классов домена.
источник
[Factory]: Usually responsible for creation of stateful objects [Dependency Injections] More likely to create stateless objects
Я не понимаю почемуЯ знаю, что этот вопрос старый, но я хотел бы добавить свои пять центов,
Я думаю, что внедрение зависимостей (DI) во многом похоже на конфигурируемый Factory Pattern (FP), и в этом смысле все, что вы можете сделать с DI, вы сможете сделать с такой фабрикой.
На самом деле, если вы используете Spring, например, у вас есть возможность автоматического подключения ресурсов (DI) или делать что-то вроде этого:
А затем используйте этот экземпляр 'mb', чтобы сделать что-нибудь. Разве это не вызов фабрике, которая вернет вам экземпляр?
Единственное реальное различие, которое я замечаю между большинством примеров FP, заключается в том, что вы можете настроить, что «myBean» находится в xml или в другом классе, и фреймворк будет работать как фабрика, но в остальном это то же самое, и вы может иметь Фабрику, которая читает конфигурационный файл или получает реализацию по мере необходимости.
И если вы спросите меня о моем мнении (и я знаю, что вы этого не сделали), я считаю, что DI делает то же самое, но просто добавляет сложности в разработку, почему?
Ну, во-первых, чтобы вы знали, какая реализация используется для любого bean-компонента, который вы автоматически связываете с DI, вы должны перейти к самой конфигурации.
но ... как насчет того обещания, что вам не нужно будет знать реализацию объекта, который вы используете? Пфф! шутки в сторону? когда вы используете такой подход ... разве вы не то же самое, что пишет реализацию? и даже если вы этого не сделаете, разве вы почти все время смотрите на то, как реализация делает то, что должна делать ??
и, наконец, не имеет значения, насколько DI-фреймворк обещает вам, что вы будете строить вещи, отделенные от него, без каких-либо зависимостей от их классов, если вы используете фреймворк, вы создаете все вокруг, если вам нужно изменить подход или рамки это не будет легкой задачей ... КОГДА-ЛИБО! ... но, поскольку вы строите все вокруг этой конкретной структуры, вместо того чтобы беспокоиться о том, какое решение лучше всего подходит для вашего бизнеса, вы столкнетесь с серьезной проблемой при этом.
Фактически, единственное реальное бизнес-приложение для подхода FP или DI, которое я вижу, - это если вам нужно изменить реализации, используемые во время выполнения , но, по крайней мере, известные мне фреймворки не позволяют вам это делать, вы должны оставить все идеально в конфигурации во время разработки, и если вам нужно, используйте другой подход.
Итак, если у меня есть класс, который по-разному работает в двух областях в одном и том же приложении (скажем, в двух компаниях холдинга), я должен сконфигурировать среду для создания двух разных bean-компонентов и адаптировать свой код для каждого из них. Разве это не то же самое, что если бы я просто написал что-то вроде этого:
так же, как это:
И это:
В любом случае вам придется что-то изменить в своем приложении, будь то классы или файлы конфигурации, но вам придется сделать это заново, развернув его.
Не было бы неплохо сделать что-то вроде этого:
И таким образом, вы устанавливаете код фабрики, чтобы получить правильную реализацию во время выполнения в зависимости от зарегистрированного пользователя предприятия ?? Теперь это будет полезно. Вы можете просто добавить новый jar с новыми классами и установить правила, возможно, даже во время выполнения (или добавить новый файл конфигурации, если вы оставите эту опцию открытой), без изменений в существующих классах. Это будет динамическая фабрика!
Разве это не было бы более полезным, чем написать две конфигурации для каждого предприятия и, может быть, даже иметь два разных приложения для каждого?
Вы можете сказать мне, что мне не нужно выполнять переключение во время выполнения, поэтому я настраиваю приложение, и, если я наследую класс или использую другую реализацию, я просто изменяю конфигурацию и повторно развертываю. Хорошо, это также может быть сделано с завода. И, честно говоря, сколько раз вы делаете это? возможно, только когда у вас есть приложение, которое будет использоваться где-то еще в вашей компании, и вы собираетесь передать код другой команде, и они будут делать такие вещи. Но эй, это также можно сделать с фабрикой, и было бы еще лучше с динамической фабрикой !!
Во всяком случае, раздел комментариев, если вы открыты, чтобы убить меня.
источник
МОК - это концепция, которая реализуется двумя способами. Создание зависимости и внедрение зависимости. Фабрика / Абстрактная фабрика - пример создания зависимости. Внедрение зависимостей - это конструктор, установщик и интерфейс. Суть IOC состоит в том, чтобы не зависеть от конкретных классов, но определить реферат методов (скажем, интерфейс / абстрактный класс) и использовать этот реферат для вызова метода конкретного класса. Как и фабричный шаблон, возвращают базовый класс или интерфейс. Подобное внедрение зависимостей использует базовый класс / интерфейс для установки значения для объектов.
источник
При внедрении зависимостей клиенту не нужно получать свои зависимости самостоятельно, все подготовлено заранее.
На фабриках кто-то должен вызывать их, чтобы доставить сгенерированные объекты туда, где они нужны.
Разница заключается главным образом в этой строке, где вызывается фабрика и извлекается созданный объект.
Но на фабриках вы должны написать эту 1 строку везде, где вам нужен такой объект. С DI вам просто нужно создать разводку (отношение между использованием и созданным объектом) один раз и просто полагаться на присутствие объекта впоследствии везде. С другой стороны, DI часто требует немного больше (насколько зависит от структуры) работы на стороне подготовки.
источник
У меня был тот же вопрос, как только я прочитал о DI и оказался на этом посту. Итак, наконец, это то, что я понял, но, пожалуйста, поправьте меня, если я не прав.
«Давным-давно существовали маленькие королевства со своими собственными руководящими органами, контролирующими и принимающими решения на основе своих собственных письменных правил. Позже сформировалось большое правительство, исключающее все эти маленькие руководящие органы, которое имеет один свод правил (конституцию) и реализуется через суды».
Руководящие органы маленьких королевств - "Фабрики"
Большое правительство - «Инжектор зависимостей».
источник
Вы можете взглянуть на эту ссылку для сравнения двух (и других) подходов в реальном примере.
В основном, когда требования меняются, вы в конечном итоге модифицируете больше кода, если используете фабрики вместо DI.
Это также справедливо для ручного DI (т. Е. Когда нет внешней структуры, которая предоставляет зависимости вашим объектам, но вы передаете их в каждом конструкторе).
источник
Большинство ответов здесь объясняют концептуальные различия и детали реализации обоих. Однако мне не удалось найти объяснение различий в применении, которое является наиболее важным для ИМО, и о котором спрашивал ОП. Итак, позвольте мне вновь открыть эту тему ...
Точно. В 90% случаев вы можете получить ссылку на объект, используя либо Factory, либо DI, и обычно вы получаете последний. В других 10% случаев использование Factory является единственно верным способом . Эти случаи включают получение объектов по переменным в параметрах времени выполнения. Нравится:
В этом случае получение
client
от DI невозможно (или, по крайней мере, требует некрасивого обходного пути). Таким образом, как общее правило для принятия решения: если зависимость может быть получена без каких-либо вычисленных во время выполнения параметров, тогда предпочтительнее DI, в противном случае используйте Factory.источник
я считаю, что DI - это способ конфигурирования или создания экземпляра бина. DI можно сделать разными способами, такими как конструктор, сеттер-геттер и т. Д.
Фабричный шаблон - это просто еще один способ создания бобов. этот шаблон будет использоваться в основном, когда вам нужно создавать объекты с использованием шаблона фабричного проектирования, поскольку при использовании этого шаблона вы не настраиваете свойства компонента, а только создаете экземпляр объекта.
Проверьте эту ссылку: Внедрение зависимостей
источник
Binoj,
Я не думаю, что вам нужно выбирать одно над другим.
Перемещение зависимого класса или интерфейса к конструктору или установщику класса следует шаблону DI. Объект, который вы передаете конструктору или множеству, может быть реализован с помощью Factory.
Когда использовать? Используйте шаблон или шаблоны, которые есть в вашей рубке разработчика. Что они чувствуют себя наиболее комфортно и легче всего понять?
источник
Полагаю, 3 важных аспекта управляют объектами и их использованием:
1. Реализация (класса вместе с инициализацией, если таковая имеется).
2. Инъекция (экземпляра, созданного таким образом), где это необходимо.
3. Управление жизненным циклом (созданного экземпляра).
Используя фабричный шаблон, достигается первый аспект (создание экземпляра), но оставшиеся два сомнительны. Класс, который использует другие экземпляры, должен жестко закодировать фабрики (а не создаваемые экземпляры), что препятствует свободным связующим способностям. Более того, управление жизненным циклом экземпляров, становится проблемой в большом приложении, где фабрика используется в нескольких местах (особенно, если фабрика не управляет жизненным циклом возвращаемого экземпляра, это становится уродливым) ,
С другой стороны, при использовании DI (шаблона IoC) все три абстрагируются вне кода (в контейнер DI), и управляемому компоненту ничего не нужно для решения этой сложности. Ослабленное соединение - очень важная архитектурная задача, которая может быть достигнута с комфортом. Еще одна важная архитектурная цель, разделение интересов, может быть достигнуто гораздо лучше, чем на фабриках.
В то время как фабрики могут быть пригодны для небольших применений, крупным было бы лучше выбрать DI, а не фабрики.
источник
Мои мысли:
Внедрение зависимости: передайте соавторы как параметры конструкторам. Dependency Injection Framework: универсальная и настраиваемая фабрика для создания объектов, передаваемых в качестве параметров конструкторам.
источник
Injection Framework - это реализация фабричного шаблона.
Все зависит от ваших требований. Если вам необходимо реализовать шаблон приложения в приложении, весьма вероятно, что ваши требования будут удовлетворены одной из множества реализаций инфраструктуры внедрения.
Вы должны развертывать свое собственное решение, только если ваши требования не могут быть выполнены какой-либо из сторонних платформ. Чем больше кода вы пишете, тем больше кода вы должны поддерживать. Кодекс является обязательством, а не активом.
Аргументы в пользу того, какую реализацию вы должны использовать, не так важны, как понимание архитектурных потребностей вашего приложения.
источник
Фабричный дизайн шаблон
Шаблон дизайна фабрики характеризуется
Вы можете наблюдать несколько вещей, когда вы спрашиваете себя, как показано ниже
Они обрабатываются инъекцией зависимости.
Внедрение зависимости
Вы можете по-разному вводить зависимость. Для простоты давайте перейдем с интерфейсом инъекции
В DI контейнер создает необходимые экземпляры и «внедряет» их в объект.
Таким образом устраняется статическая реализация.
Пример:
источник
Из номинала они выглядят одинаково
Проще говоря, Factory Pattern, Creational Pattern помогает создать нам объект - «Определить интерфейс для создания объекта». Если у нас есть ключевое значение типа пула объектов (например, словарь), передав ключ к фабрике (я имею в виду простой шаблон фабрики), вы можете разрешить тип. Работа выполнена! С другой стороны, структура внедрения зависимостей (например, Structure Map, Ninject, Unity и т. Д.), Похоже, делает то же самое.
Но ... "Не изобретай велосипед"
С архитектурной точки зрения это связующий слой и «Не изобретай велосипед».
Для приложения уровня предприятия концепция DI - это скорее архитектурный уровень, который определяет зависимости. Чтобы еще больше упростить это, вы можете думать об этом как об отдельном библиотечном проекте, который разрешает зависимости. Основное приложение зависит от этого проекта, где решатель зависимостей относится к другим конкретным реализациям и разрешению зависимостей.
В дополнение к «GetType / Create» из Фабрики, чаще всего нам нужны дополнительные функции (возможность использовать XML для определения зависимостей, макетирование и модульное тестирование и т. Д.). Поскольку вы ссылались на Карту структуры, посмотрите на список возможностей Карты структуры . Это явно больше, чем просто разрешение простого сопоставления объектов. Не изобретай велосипед!
Если у вас есть только молоток, все выглядит как гвоздь
В зависимости от ваших требований и типа создаваемого вами приложения, вам необходимо сделать выбор. Если в нем всего несколько проектов (может быть один или два ...) и в нем мало зависимостей, вы можете выбрать более простой подход. Это похоже на использование доступа к данным ADO .Net по сравнению с использованием Entity Framework для простых вызовов базы данных 1 или 2, где внедрение EF в этом сценарии является излишним.
Но для более крупного проекта или если ваш проект становится больше, я настоятельно рекомендую иметь слой DI с каркасом и освободить место для изменения используемой вами структуры DI (используйте фасад в основном приложении (веб-приложение, веб-интерфейс, рабочий стол) ..так далее.).
источник
С фабрикой вы можете группировать связанные интерфейсы, поэтому, если переданные параметры могут быть сгруппированы на фабрике, то это также хорошее решение для
constructor overinjection
просмотра этого кода *):Посмотрите на конструктор, вам нужно только передать
IAddressModelFactory
туда, так что меньше параметров *):Вы видите во
CustomerController
многих переданных параметрах, да, вы можете видеть это как,constructor overinjection
но именно так работает DI. И нет ничего плохого в этомCustomerController
.*) Код от nopCommerce.
источник
Говоря простым языком, метод зависимости зависимостей от фабрики подразумевает механизм принудительной и последовательной обработки.
Механизм извлечения : класс косвенно зависит от Factory Method, который, в свою очередь, зависит от конкретных классов.
Толкающий механизм : корневой компонент может быть сконфигурирован со всеми зависимыми компонентами в одном месте, что способствует высокому техническому обслуживанию и слабому сцеплению.
С фабричным методом ответственность по-прежнему лежит на классе (хотя и косвенно) за создание нового объекта, где, как и при внедрении зависимостей, эта ответственность передается на аутсорсинг (но за счет утечки абстракции)
источник
Я думаю, что они ортогональны и могут быть использованы вместе. Позвольте мне показать вам пример, с которым я недавно столкнулся на работе:
Мы использовали Spring Framework в Java для DI. Singleton class (
Parent
) должен был создать новые объекты другого класса (Child
), и у них были сложные соавторы:В этом примере
Parent
необходимо получатьDepX
экземпляры только для того, чтобы передать ихChild
конструктору. Проблемы с этим:Parent
имеет больше знаний,Child
чем следуетParent
имеет больше сотрудников, чем должноChild
включает изменениеParent
Это когда я понял,
Factory
что идеально подходит здесь:Child
класса, как видно изParent
Child
, которое может быть централизовано в конфигурации DI.Это упрощенный
Parent
класс иChildFactory
класс:источник
Вы используете внедрение зависимостей, когда точно знаете, какой тип объектов вам нужен в данный момент. В то время как в случае с фабричным шаблоном вы просто делегируете процесс создания объектов фабрике, так как не знаете, какой именно тип объектов вам нужен.
источник
Я использую оба для создания стратегии Inversion Of Control с большей удобочитаемостью для разработчиков, которым необходимо поддерживать ее после меня.
Я использую Фабрику для создания различных объектов Layer (Бизнес, Доступ к данным).
Это увидит другой разработчик, и при создании объекта Business Layer он смотрит в BusinessFactory, и Intellisense предоставляет разработчику все возможные бизнес-уровни для создания. Не нужно играть в игру, найдите интерфейс, который я хочу создать.
Эта структура уже является инверсией контроля. Я больше не несу ответственности за создание конкретного объекта. Но вам все равно нужно обеспечить внедрение зависимостей, чтобы можно было легко что-то менять. Создание своего собственного Dependency Injection нелепо, поэтому я использую Unity. В CreateCarBusiness () я прошу Unity to Resolve, к какому классу относится этот класс и его время жизни.
Итак, мой код Factory Inpendency Injection выглядит так:
Теперь у меня есть преимущество обоих. Мой код также более удобен для чтения другими разработчиками по сравнению с областями моих объектов, которые я использую, вместо Constructor Dependency Injection, которое просто говорит, что каждый объект доступен при создании класса.
Я использую это, чтобы изменить свой доступ к данным базы данных на пользовательский кодированный слой доступа к данным при создании модульных тестов. Я не хочу, чтобы мои модульные тесты связывались с базами данных, веб-серверами, серверами электронной почты и т. Д. Им нужно тестировать мой бизнес-уровень, потому что именно в этом и заключается интеллект.
источник
Использование внедрения зависимостей, на мой взгляд, намного лучше, если вы: 1. развертываете свой код в небольшом разделе, потому что он хорошо справляется с развязкой одного большого кода. 2. Тестируемость - это один из случаев, когда DI можно использовать, потому что вы можете легко издеваться над неразделенными объектами. с помощью интерфейсов вы можете легко макетировать и тестировать каждый объект. 3. Вы можете одновременно пересматривать каждую часть программы без необходимости кодировать другую ее часть, поскольку она слабо отделена.
источник