Инъекция зависимостей против Factory Образец

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

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

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

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

Ответ 1

При использовании factory ваш код по-прежнему фактически отвечает за создание объектов. По DI вы передаете эту ответственность другому классу или структуре, которая отделена от вашего кода.

Ответ 2

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

Ответ 3

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

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

class Car
{
    private Engine engine;
    private SteeringWheel wheel;
    private Tires tires;

    public Car(Engine engine, SteeringWheel wheel, Tires tires)
    {
        this.engine = engine;
        this.wheel = wheel;
        this.tires = tires;
    }
}

завод

Собирает кусочки вместе, чтобы создать законченный объект, и скрывает конкретный тип от звонящего.

static class CarFactory
{
    public ICar BuildCar()
    {
        Engine engine = new Engine();
        SteeringWheel steeringWheel = new SteeringWheel();
        Tires tires = new Tires();
        ICar car = new RaceCar(engine, steeringWheel, tires);
        return car;
    }   
}

Результат

Как видите, фабрики и DI дополняют друг друга.

static void Main()
{
     ICar car = CarFactory.BuildCar();
     // use car
}

Ты помнишь златовласку и трех медведей? Ну, инъекция зависимостей вроде этого. Вот три способа сделать то же самое.

void RaceCar() // example #1
{
    ICar car = CarFactory.BuildCar();
    car.Race();
}

void RaceCar(ICarFactory carFactory) // example #2
{
    ICar car = carFactory.BuildCar();
    car.Race();
}

void RaceCar(ICar car) // example #3
{
    car.Race();
}

Пример № 1 - Это худший вариант, потому что он полностью скрывает зависимость. Если бы вы смотрели на этот метод как на черный ящик, вы бы не поняли, что для этого нужна машина.

Пример № 2 - Это немного лучше, потому что теперь мы знаем, что нам нужна машина, так как мы проходим на автомобильном заводе. Но на этот раз мы проходим слишком много, так как все, что нужно на самом деле, - это машина. Мы проезжаем по фабрике только для того, чтобы построить машину, когда машину можно будет построить вне метода и сдать.

Пример № 3 - Это идеально, потому что метод запрашивает именно то , что ему нужно. Не слишком много или слишком мало. Мне не нужно писать MockCarFactory только для создания MockCars, я могу передать макет прямо. Он прямой и интерфейс не лжет.

Этот Google Tech Talk от Misko Hevery удивителен и является основой того, из чего я получил свой пример. http://www.youtube.com/watch?v=XcT4yYu_TTs

Ответ 4

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

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

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

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

Ответ 5

Причина зависимостей Injection (DI) и Factory аналогична тем, что они представляют собой две реализации инверсии управления (IoC), которая является программной архитектурой. Проще говоря, это два решения одной и той же проблемы.

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

Следует отметить, что шаблоны Factory (или действительно абстрактные Factory, которые являются фабриками, возвращающими новые фабрики, возвращающие ссылки на объекты), могут быть записаны для динамического выбора или ссылки на тип или класс объекта, запрашиваемого при запуске время. Это делает их очень похожими (даже больше, чем DI) на шаблон Service Locator, который является другой реализацией IoC.

Схема дизайна Factory довольно старая (с точки зрения программного обеспечения) и была вокруг некоторое время. Начиная с недавней популярности архитектурного шаблона IoC, он имеет возрождение.

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

Ответ 6

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

Ответ 7

Управление жизненным циклом - это одна из обязанностей, которую контейнеры зависимостей принимают в дополнение к инстанцированию и инъекции. Тот факт, что контейнер иногда содержит ссылку на компоненты после создания экземпляра, является причиной того, что он называется "контейнером", а не factory. Контейнеры для инъекций зависимостей обычно содержат только ссылку на объекты, которые ему нужны для управления жизненными циклами или которые повторно используются для будущих инъекций, таких как одиночные или мухоловки. Когда сконфигурировано создание новых экземпляров некоторых компонентов для каждого вызова контейнера, контейнер обычно просто забывает о созданном объекте.

От: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html

Ответ 8

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

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

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

Ответ 9

Я знаю, что этот вопрос старый, но я бы хотел добавить пять центов,

Я думаю, что инъекция зависимостей (DI) во многом похожа на настраиваемый шаблон Factory (FP), и в этом смысле все, что вы могли бы сделать с DI, вы сможете сделать это с помощью factory.

На самом деле, если вы используете spring, например, у вас есть возможность автономных ресурсов (DI) или сделать что-то вроде этого:

MyBean mb = ctx.getBean("myBean");

И затем используйте этот экземпляр "mb", чтобы что-то сделать. Разве это не вызов Factory, который вернет вам экземпляр?

Единственная реальная разница, которую я замечаю в большинстве примеров FP, заключается в том, что вы можете настроить, что "myBean" находится в xml или в другом классе, а структура будет работать как factory, но кроме этого то же самое, и у вас наверняка есть Factory, который читает конфигурационный файл или получает реализацию по мере необходимости.

И если вы спросите меня о моем мнении (И я знаю, что вы этого не сделали), я считаю, что DI делает то же самое, но просто добавляет больше сложности в развитие, почему?

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

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

и для одной последней вещи не важно, насколько каркас DI promises, что вы будете создавать из него развязанный, без зависимостей от их классы, если вы используете фреймворк, который вы все создаете, , если вам нужно изменить подход или структуру, это будет непростая задача... КОГДА-ЛИБО!... но, поскольку вы строите все вокруг этой конкретной структуры вместо того, чтобы беспокоиться о том, что является лучшим решением для вашего бизнеса, тогда вы столкнетесь с проблемой biiig при этом.

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

Итак, если у меня есть класс, который по-разному работает в двух областях в одном приложении (скажем, две компании холдинга), мне нужно настроить фреймворк для создания двух разных beans и адаптировать мой код для использования каждый. Разве это не так, как если бы я просто написал что-то вроде этого:

MyBean mb = MyBeanForEntreprise1(); //In the classes of the first enterprise
MyBean mb = MyBeanForEntreprise2(); //In the classes of the second enterprise

то же самое, что и:

@Autowired MyBean mbForEnterprise1; //In the classes of the first enterprise
@Autowired MyBean mbForEnterprise2; //In the classes of the second enterprise

И это:

MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise1"); //In the classes of the first enterprise
MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise2"); //In the classes of the second enterprise

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

Было бы неплохо сделать что-то вроде этого:

MyBean mb = (MyBean)MyFactory.get("mb"); 

И таким образом вы установите код Factory, чтобы получить правильную реализацию во время выполнения в зависимости от зарегистрированного пользовательского предприятия? Теперь ЭТО было бы полезно. Вы можете просто добавить новую банку с новыми классами и установить правила, возможно, даже во время выполнения (или добавить новый файл конфигурации, если вы оставите этот параметр открытым), никаких изменений в существующих классах. Это будет динамический factory!

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

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

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

Ответ 10

теория

Есть два важных момента для рассмотрения:

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

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

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

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

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

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

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

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

enter image description here

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

  1. Доменный уровень и использование фабрик

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

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

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

завод

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

enter image description here

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

  1. Внедрение зависимостей Внедрение зависимостей чаще используется для слоев без состояний, таких как хранилище и сервис.

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

enter image description here

Ответ 11

IOC - это концепция, которая реализуется двумя способами. Создание зависимостей и зависимость, Factory/Аннотация factory - пример создания зависимости. Инъекция зависимостей - это конструктор, сеттер и интерфейс. Ядро IOC состоит в том, чтобы не зависеть от конкретных классов, а определять абстрактные методы (скажем, интерфейс/абстрактный класс) и использовать этот абстрактный метод вызова конкретного класса. Как шаблон factory возвращает базовый класс или интерфейс. Подобная инъекция зависимости использует базовый класс/интерфейс для установки значения для объектов.

Ответ 12

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

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

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

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

Ответ 13

У меня был тот же вопрос, как только я прочитал о DI и оказался на этом посту. Поэтому, наконец, это то, что я понял, но, пожалуйста, исправьте меня, если я ошибаюсь.

"Давным-давно были небольшие королевства со своими руководящими органами, которые контролировали и принимали решения на основе их собственных письменных правил. Позже сформировалось большое правительство, ликвидировавшее все эти небольшие руководящие органы, которые имеют один набор правил (конституций) и осуществляются через суды"

Руководящие органы маленьких королевств - это "Заводы"

Большое правительство - это "Инъектор зависимостей".

Ответ 14

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

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

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

Ответ 15

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

Factory pattern - это еще один способ создания экземпляра beans. этот шаблон будет использоваться, главным образом, когда вам нужно создавать объекты с использованием шаблона проектирования factory, так как при использовании этого шаблона вы не настраиваете свойства bean, а только создаете экземпляр объекта.

Проверьте эту ссылку: Инъекция зависимостей

Ответ 16

Binoj,

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

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

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

Ответ 17

Я считаю, что 3 важных аспекта управляют объектами и их использованием:
1. Активация (класса вместе с инициализацией, если таковая имеется).
2. Инъекция (созданного таким образом экземпляра), где это необходимо.
3. Управление жизненным циклом (созданного таким образом экземпляра).

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

С другой стороны, с помощью DI (шаблона IoC) все три абстрагируются вне кода (в контейнер DI), а управляемый bean ничего не требует об этой сложности. Loose Coupling, очень важная архитектурная цель может быть достигнута спокойным комфортом. Еще одна важная архитектурная цель: разделение проблем может быть достигнуто намного лучше, чем фабрики.

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

Ответ 18

Мои мысли:

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

Ответ 19

Injection Framework представляет собой реализацию шаблона Factory.

Все зависит от ваших требований. Если вам нужно реализовать шаблон Factory в приложении, весьма вероятно, что ваши требования будут удовлетворены одним из множества реализаций реализации инъекций.

Вы должны только развертывать собственное решение, если ваши требования не могут быть удовлетворены ни одной из сторонних инфраструктур. Чем больше кода вы пишете, тем больше кода вы должны поддерживать. Код - это обязательство, не являющееся активом.

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

Ответ 20

Factory Шаблон проектирования

Конструктивный шаблон factory характеризуется

  • Интерфейс
  • Классы реализации
  • A factory

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

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

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

Включение зависимостей

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

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

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

Пример:

public class MyClass{

  MyInterface find= null;

  //Constructor- During the object instantiation

  public MyClass(MyInterface myInterface ) {

       find = myInterface ;
  }

  public void myMethod(){

       find.doSomething();

  }
}

Ответ 21

Из номинала они выглядят одинаково

В очень простых терминах Factory Pattern, шаблон создания помогает создать нам объект - "Определить интерфейс для создания объекта". Если у нас есть ключевое значение типа пула объектов (например, Словарь), передавая ключ в Factory (я имею в виду шаблон Simple Factory), вы можете разрешить Type. Работа выполнена! С другой стороны, Framework Injection Dependency (например, Structure Map, Ninject, Unity... и т.д.), Похоже, делает то же самое.

Но... "Не изобретайте велосипед"

С архитектурной точки зрения его связывающий слой и "Не изобретать велосипед".

Для приложений корпоративного уровня концепция DI является скорее архитектурным слоем, который определяет зависимости. Чтобы упростить это, вы можете думать об этом как о отдельном проекте classlibrary, который разрешает зависимость. Основное приложение зависит от этого проекта, где Dependency resolver ссылается на другие конкретные реализации и на разрешение зависимостей.

Помимо "GetType/Create" из Factory, чаще всего нам нужно больше возможностей (возможность использования XML для определения зависимостей, издевательств и модульного тестирования и т.д.). Поскольку вы ссылались на Структурную карту, просмотрите Список структурных карт. Это явно больше, чем просто разрешение простого сопоставления объектов. Не изобретайте велосипед!

Если у вас есть молот, все выглядит как гвоздь

В зависимости от ваших требований и типа используемого вами приложения вам нужно сделать выбор. Если у него всего несколько проектов (может быть один или два..) и включает в себя несколько зависимостей, вы можете выбрать более простой подход. Это похоже на использование доступа к данным ADO.Net с использованием Entity Framework для простых 1 или 2 вызовов базы данных, где внедрение EF является излишним в этом сценарии.

Но для более крупного проекта или если ваш проект станет больше, я бы настоятельно рекомендовал иметь слой DI с каркасом и освободить место для изменения используемой среды DI (используйте фасад в главном приложении (веб-приложение, веб-приложение) Api, Desktop..etc.).

Ответ 22

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

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

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

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

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

Ответ 23

С помощью factory вы можете группировать связанные интерфейсы, поэтому, если переданные параметры можно сгруппировать в factory, то это также хорошее решение для constructor overinjection посмотреть на этот код *):

public AddressModelFactory(IAddressAttributeService addressAttributeService,
        IAddressAttributeParser addressAttributeParser,
        ILocalizationService localizationService,
        IStateProvinceService stateProvinceService,
        IAddressAttributeFormatter addressAttributeFormatter)
    {
        this._addressAttributeService = addressAttributeService;
        this._addressAttributeParser = addressAttributeParser;
        this._localizationService = localizationService;
        this._stateProvinceService = stateProvinceService;
        this._addressAttributeFormatter = addressAttributeFormatter;
    }

Посмотрите на конструктор, вам нужно передать только IAddressModelFactory, поэтому меньше параметров *):

 public CustomerController(IAddressModelFactory addressModelFactory,
        ICustomerModelFactory customerModelFactory,
        IAuthenticationService authenticationService,
        DateTimeSettings dateTimeSettings,
        TaxSettings taxSettings,
        ILocalizationService localizationService,
        IWorkContext workContext,
        IStoreContext storeContext,
        ICustomerService customerService,
        ICustomerAttributeParser customerAttributeParser,
        ICustomerAttributeService customerAttributeService,
        IGenericAttributeService genericAttributeService,
        ICustomerRegistrationService customerRegistrationService,
        ITaxService taxService,
        CustomerSettings customerSettings,
        AddressSettings addressSettings,...

Вы видите в CustomerController много переданных параметров. Да, вы можете видеть это как constructor overinjection, но это так, как работает DI. И нет ничего плохого в CustomerController.

*) Код из nopCommerce.

Ответ 24

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

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

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

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

Ответ 25

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

Мы использовали Spring Framework в Java для DI. Класс Singleton (Parent) должен был создать новые объекты другого класса (Child), и у них были сложные соавторы:

@Component
class Parent {
    // ...
    @Autowired
    Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    void method(int p) {
        Child c = new Child(dep1, dep2, ..., depN, p);
        // ...
    }
}

В этом примере Parent должен получать экземпляры DepX только для передачи их конструктору Child. Проблемы с этим:

  1. Parent имеет больше знаний о Child чем должен
  2. Parent имеет больше соавторов, чем должно
  3. Добавление зависимостей в Child предполагает изменение Parent

Это когда я понял, что Factory идеально подошла бы здесь:

  1. Он скрывает все, кроме истинных параметров класса Child, как видно из Parent
  2. Он включает в себя знания о создании Child элементов, которые могут быть централизованы в конфигурации DI.

Это упрощенный класс Parent класс ChildFactory:

@Component
class Parent {
    // ...
    @Autowired
    Parent(ChildFactory childFactory) {
        this.childFactory = childFactory;
    }

    void method(int p) {
        Child c = childFactory.newChild(p);
        // ...
    }
}

@Component
class ChildFactory {
    // ...
    @Autowired
    Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
        this.dep1 = dep1;
        this.dep2 = dep2;
        // ...
        this.depN = depN;
    }

    Child newChild(int p) {
        return new Child(dep1, dep2, ..., depN, p);
    }
}

Ответ 26

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

Я использую Фабрику для создания различных объектов Layer (Бизнес, Доступ к данным).

ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness();

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

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

Таким образом, моя структура Factory Inpendency Injection выглядит так:

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

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

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

Ответ 27

Использование инъекции зависимостей намного лучше, на мой взгляд, если вы: 1. развертывание вашего кода в небольшом разделе, потому что он отлично справляется с развязкой одного большого кода. 2. testability является одним из случаев, когда DI одобрен для использования, потому что вы можете легко издеваться над не разделенными объектами. с помощью интерфейсов вы можете легко издеваться и тестировать каждый объект. 3. вы можете одновременно пересматривать каждую часть программы без необходимости кодировать другую ее часть, так как она свободно отделяется.