DI контейнер, фабрика или новый для эфемерных объектов? - PullRequest
9 голосов
/ 14 января 2010

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

Например, я могу просто new объект, когда у меня есть данные:

UserCredentials creds =
    new UserCredentials(dialog.getUsername(), dialog.getPassword());

Или я мог бы использовать фабрику:

UserCredentials creds =
    CredentialsFactory.create(dialog.getUsername(), dialog.getPassword());

Или я мог бы использовать провайдера в контейнере DI (который в этом случае по сути был бы фабрикой, управляемой параметрами). [Пример кода опущен.]

Кажется, что неправильно использовать контейнер DI для чего-то такого простого, но также неправильно не использовать его в полной мере.

Ответы [ 4 ]

8 голосов
/ 14 января 2010

Как всегда, это зависит, но, как правило, статическая фабрика, такая как ваш второй вариант, редко бывает хорошей идеей.

new создание объекта UserCredential выглядит справедливым выбором, поскольку класс UserCredentials выглядит как отдельный, конкретный класс, который может быть полностью создан со всеми его инвариантами из имени пользователя и пароля.

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

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

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

3 голосов
/ 14 января 2010

В блоге тестирования Google есть сообщение, которое пытается ответить на этот вопрос . Основная идея состоит в том, что вы можете классифицировать каждый из ваших классов как «newable» или «injectable», и что можно просто «обновлять» newables.

Различаю 2 основные категории "новинок":

  • значения, такие как int, string, DateTime и т. Д.
  • объекты, такие как Customer, Order, Employee и так далее. Я думаю, что ваш UserCredentials класс подпадает под этот заголовок.

Важно понимать, что newables может иметь (тестируемое) поведение . Если вы ошибаетесь, думая, что у newables не должно быть никаких поведенческих или модульных тестов, вы в конечном итоге получите модель анемичного домена anti-pattern.

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

Кроме того, новичкам разрешено знать о инъекционных препаратах, но они только временно взаимодействуют с ними. Например, UserCredentials не должен принимать IUserDatabase в качестве аргумента конструктора. Вместо этого может быть метод UserCredentials.Verify(IUserDatabase).

edit: В настоящее время я больше не уверен в том, что написал выше. Сущности также можно создавать с помощью (инъецируемых) фабрик, вместо непосредственного вызова их конструктора. Затем фабричная реализация может внедрить вещи в сущность.

0 голосов
/ 14 января 2010

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

0 голосов
/ 14 января 2010

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

Это действительно зависит, когда и где вам понадобится этот объект, и будут ли в результате ненужные зависимости.

...