Я читал о шаблоне Factory и наткнулся на статьи, в которых предлагается использовать шаблон Factory в сочетании с внедрением зависимостей для максимальной возможности повторного использования и тестирования. Хотя мне не удалось найти никаких конкретных примеров этого гибрида Factory-DI, я собираюсь попробовать и привести несколько примеров кода моей интерпретации . Однако на самом деле мой вопрос заключается в том, как этот подход улучшает тестируемость.
Итак, у нас есть класс Widget
:
public class Widget {
// blah
}
И мы хотим включить WidgetFactory
для управления построением Widget
s:
public interface WidgetFactory {
public abstract static Widget getWidget();
}
public class StandardWidgetFactory implements WidgetFactory {
@Override
public final static Widget getWidget() {
// Creates normal Widgets
}
}
public class TestWidgetFactory implements WidgetFactory {
@Override
public final static Widget getWidget() {
// Creates test/mock Widgets for unit testing purposes
}
}
Хотя в этом примере используется Spring DI (это единственный API, с которым у меня есть опыт), на самом деле не имеет значения, говорим мы о Guice или какой-либо другой инфраструктуре IoC; идея здесь в том, что теперь мы собираемся внедрить правильную реализацию WidgetFactory
во время выполнения в зависимости от того, тестируем ли мы код или работаем нормально. В Spring конфигурация beans может выглядеть так:
Затем в коде:
WidgetFactory wf = applicationContext.getBean("injected-factory");
Widget w = wf.getWidget();
Таким образом, переменная среды (уровня развертывания), возможно, определенная в .properties где-нибудь, решает, будет ли Spring DI внедрять StandardWidgetFactory
или TestWidgetFactory
.
Правильно ли я делаю?!? Кажется, ужасно много инфраструктуры просто обеспечивает хорошую тестируемость для моего виджета
. Не то чтобы я против этого, но мне это просто кажется чрезмерной инженерией.
Я спрашиваю об этом потому, что у меня будут другие объекты в других пакетах, в которых есть методы, использующие объекты Widget
внутри них. Возможно, что-то вроде:
public class Fizz {
public void doSomething() {
WidgetFactory wf = applicationContext.getBean("injected-factory");
Widget widget = wf.getWidget();
int foo = widget.calculatePremable(this.rippleFactor);
doSomethingElse(foo);
}
}
Без этой огромной, казалось бы, чрезмерно сложной настройки у меня не было бы возможности внедрить «mock Widgets
» в свой модульный тест для Fizz :: doSomething ( )
.
Итак, я разорван: с одной стороны, мне кажется, что я слишком много думаю о вещах - что я вполне могу делать (если моя интерпретация неверна ). С другой стороны, я не вижу никакого чистого способа обойти это.
В качестве перехода к второстепенному вопросу это также вызывает у меня еще одно огромное беспокойство: если моя интерпретация верна (или даже в некоторой степени верна), значит ли это, что нам нужны Фабрики
для каждого объекта ?! ?
Похоже на чрезмерную инженерию ! Какая отсечка? Какая черта на песке определяет, когда использовать Фабрику, а когда нет ?! Спасибо за любую помощь и извинения за подробный вопрос. У меня просто кружится голова.