Я недавно подумал об этом (поэтому нашел этот вопрос), и хотя у меня нет ответа, я думал, что поделюсь своими мыслями.
- Конструкторы «в идеале»следует только установить состояние объекта, то есть: несколько:
this.member = member;
На мой взгляд, это хорошо сочетается с IoC, наследованием, тестированием и просто приятно пахнет.
Однако иногда требуется тяжелый подъем, поэтому я пытался сделать следующее:
Это означает абстрагирование этого кода инициализации.другому классу и передаю его. Это обычно возможно, если тяжелая работа не является действительно вашей ответственностью за объекты, так что это фактически делает рефакторинг к более приятному коду.
Если это невозможно, и вам нужно инициализировать состояниедля вашего класса перед использованием, затем добавьте метод initialse.Это добавляет временную зависимость в ваш код, но это не обязательно плохо, особенно при использовании контейнеров IoC:
Скажем, CarEngine
требует DrivingAssistComputer
, а DrivingAssistComputer
требует тяжелой инициализации, т.е.Загрузка всех параметров, проверка погодных условий и т. Д. Следует также отметить, что CarEngine
напрямую не взаимодействует с DrivingAssistComputer
, ему просто нужно присутствовать, выполняя свою функцию на стороне.На самом деле двигатель может не работать должным образом, если DrivingAssistComputer
не работает в фоновом режиме (где-то не меняя состояние).Если мы используем IoC, то имеем:
// Without initialise (i.e. initialisation done in computer constructor)
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
this.injectors = injectors;
// No need to reference computer as we dont really interact with it.
}
...
Итак, мы имеем аргумент конструктора, помечающий computer
как зависимость, но фактически не использующий его.Так что это уродливо, но давайте добавим метод Initialise:
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
this.injectors = injectors;
// This ofcourse could also be moved to CarEngine.Initialse
computer.Initialise();
}
...
Все еще не связный класс, но, по крайней мере, мы знаем, что зависим от компьютера, даже если мы не взаимодействуем напрямую с ним вне конструктора.
Другой вариант, конечно, заключается в том, чтобы иметь CarEngineFactory, который выполняет:
CarEngine CreateEngine(FuelInjectors injectors) {
new DrivingAssistComputer().Initialise();
return new CarEngine(injectors);
}
...
Однако я считаю, что фабрики и IoC просто путают матрицу, поэтому я выбрал бы второй вариант.
Хотелось бы услышать некоторые мысли по этому поводу.
Редактировать 1: Другая опция, которую я пропустил выше, - это метод Initialise, но перенос этого вызова в модуль инициализации IoC.Таким образом, создание и инициализация все еще несколько заключены в капсулу.