Есть ли когда-либо случай для «нового» при использовании внедрения зависимости? - PullRequest
16 голосов
/ 10 февраля 2009

Означает ли внедрение зависимостей, что вам никогда не нужно ключевое слово 'new'? Или целесообразно напрямую создавать простые листовые классы, такие как коллекции?

В приведенном ниже примере я вставляю компаратор, запрос и dao, но SortedSet создается непосредственно:

public Iterable<Employee> getRecentHires()
{
    SortedSet<Employee> entries = new TreeSet<Employee>(comparator);
    entries.addAll(employeeDao.findAll(query));
    return entries;
}

Ответы [ 6 ]

9 голосов
/ 10 февраля 2009

То, что Dependency Injection - это полезный шаблон, не означает, что мы используем его для всего. Даже при использовании DI часто возникает необходимость в new . Пока не удаляйте новое.

6 голосов
/ 10 февраля 2009

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

Для сотрудничающих классов, таких как TreeSet, я обычно не внедряю их, потому что обычно нет необходимости макетировать простые классы, подобные этим.

И последнее замечание: когда поле не может быть введено по какой-либо причине, но я все еще хотел бы смоделировать его в тесте, я обнаружил, что класс Junit-addons PrivateAccessor полезен для возможности переключите приватное поле класса на фиктивный объект, созданный EasyMock (или jMock или любым другим фреймворком, который вы предпочитаете).

4 голосов
/ 10 февраля 2009

Нет ничего плохого в использовании new , как показано в вашем фрагменте кода.

Рассмотрим случай добавления фрагментов строки. Почему вы хотите попросить инжектор для StringBuilder?

В другой ситуации, с которой я столкнулся, мне нужно было запустить поток в соответствии с жизненным циклом моего контейнера. В этом случае мне пришлось выполнить new Thread () , потому что мой Injector был создан после вызова метода обратного вызова для запуска контейнера. И как только инжектор был готов, я вручную ввел некоторые управляемые классы в свой подкласс Thread.

0 голосов
/ 21 февраля 2009

Это правда, что в современной среде на основе фреймворков объекты создаются все реже и реже. Например, сервлеты создаются в контейнере сервлетов, бины в Spring создаются в Spring и т. Д.

Тем не менее, при использовании слоя постоянства вы будете создавать экземпляры сохраняемых объектов до того, как они будут сохранены. Например, при использовании Hibernate вы будете вызывать new для своего сохраненного объекта перед вызовом save на вашем HibernateTemplate.

0 голосов
/ 16 февраля 2009

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

Так что, когда DI излишне, я использую 'new' и просто позволяю ему катиться.

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

надеюсь, это поможет.

0 голосов
/ 10 февраля 2009

Да, конечно.

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

Однако достаточно ситуаций, когда вы точно знаете, что хотите создать, поэтому DI не нужен.

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

...