Фабрики имеют много преимуществ, которые позволяют в некоторых ситуациях создавать элегантные проекты. Одним из них является то, что вы можете установить свойства объектов, которые вы позже хотите создать, в одном месте, создав фабрику, а затем передать эту фабрику. Но часто вам не нужно этого делать. В этом случае использование Factory просто добавляет дополнительную сложность, фактически не давая вам ничего взамен. Давайте возьмем эту фабрику, например:
WidgetFactory redWidgetFactory = new ColoredWidgetFactory(COLOR_RED);
Widget widget = redWidgetFactory.create();
Одной альтернативой шаблону Factory является очень похожий шаблон Builder. Основное отличие состоит в том, что свойства объектов, созданных Фабрикой, устанавливаются при инициализации Фабрики, тогда как Builder инициализируется с состоянием по умолчанию, а все свойства устанавливаются впоследствии.
WidgetBuilder widgetBuilder = new WidgetBuilder();
widgetBuilder.setColor(COLOR_RED);
Widget widget = widgetBuilder.create();
Но когда ваша проблема заключается в переподготовке, замена Фабрики на Строителя, скорее всего, не является улучшением.
Самая простая замена для любого шаблона - это, конечно, создание экземпляров объекта с помощью простого конструктора с new
оператором:
Widget widget = new ColoredWidget(COLOR_RED);
Однако конструкторы имеют существенный недостаток в большинстве объектно-ориентированных языков: они должны возвращать объект именно этого класса и не могут возвращать подтип.
Когда вам нужно выбрать подтип во время выполнения, но вы не хотите создавать для этого целый новый класс Builder или Factory, вы можете использовать вместо этого метод factory. Это статический метод класса, который возвращает новые экземпляры этого класса или одного из его подклассов. Фабрика, которая не поддерживает никакого внутреннего состояния, часто может быть заменена таким фабричным методом:
Widget widget = Widget.createColoredWidget(COLOR_RED); // returns an object of class RedColoredWidget
Новая функция в Java 8 - ссылки на методы, которые позволяют передавать методы, как если бы вы работали с фабрикой без сохранения состояния. Удобно, что все, что принимает ссылку на метод, также принимает любой объект, который реализует тот же функциональный интерфейс, который также может быть полноценной фабрикой с внутренним состоянием, так что вы можете легко представить фабрики позже, когда увидите причину для этого.