Как избежать безумия конструктора Внедрения зависимости?

Я нахожу, что мои конструкторы начинают быть похожими на это:

public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )

с когда-либо увеличением списка параметров. Так как "Контейнер" является моим контейнером внедрения зависимости, почему не может я просто сделать это:

public MyClass(Container con)

для каждого класса? Каковы оборотные стороны? Если я делаю это, такое чувство, что я использую прославленные помехи. Совместно используйте свои мысли о безумии Внедрения зависимости и МОК.

287
задан rae1 11 March 2013 в 04:24
поделиться

4 ответа

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

Одним из замечательных преимуществ Constructor Injection является то, что он делает нарушения принципа единой ответственности вопиюще очевидными.

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

393
ответ дан 23 November 2019 в 01:48
поделиться

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

60
ответ дан 23 November 2019 в 01:48
поделиться

Какую среду внедрения зависимостей вы используете? Вы пробовали вместо этого использовать внедрение на основе установщика?

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

В Spring вы можете передавать требуемые значения с помощью методов установки, и вы можете использовать аннотации @required, чтобы принудительно внедрить их. Обратной стороной является то, что вам нужно переместить код инициализации из конструктора в другой метод и вызвать Spring после внедрения всех зависимостей, пометив его с помощью @PostConstruct. Я не уверен насчет других фреймворков, но предполагаю, что они делают что-то подобное.

Оба способа работают, это вопрос предпочтения.

-7
ответ дан 23 November 2019 в 01:48
поделиться

Проблема не в сложности передачи параметров. Проблема в том, что ваш класс делает слишком много, и его следует больше разбивать.

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

25
ответ дан 23 November 2019 в 01:48
поделиться