Шаблон проектирования фабричных методов в контексте интерфейсов Java?

Я новичок в Java, и книга, которую я использую для изучения, кажется, содержит загадочные примеры и предложения, которые полностью меня смущают.

Я понимаю, что такое интерфейсы и как/где применять эту концепцию в реальном мире. Но что такое фабричные методы? Термин «фабричный метод» неоднозначен (JavaScript имеет для этого другое значение), поэтому я предоставляю фрагмент, который есть в книге, чтобы прояснить мой вопрос. Вот код:

interface Service {
    void method1();
    void method2();
}

interface ServiceFactory {
    Service getService();
}

Интерфейс Service — это обычный интерфейс. Интерфейс ServiceFactory выглядит как обычный интерфейс, но это "фабричный метод". Что это? Что это решает и почему я должен их использовать?


person Fresher    schedule 03.08.2016    source источник
comment
Строго говоря, ServiceFactory тоже нормальный интерфейс. Фабричный метод нуждается в некоторой реализации (начиная с Java 8, это может быть метод по умолчанию в интерфейсе), поскольку он должен производить (создавать) экземпляр некоторого типа (отсюда и термин фабрика). Вы можете указать фабричный метод в интерфейсе, но вам все равно нужен конкретный класс фабрики, который создает определенные типы. См. en.wikipedia.org/wiki/Factory_method_pattern.   -  person Andreas Fester    schedule 03.08.2016


Ответы (2)


«Фабричный метод» — это метод, который создает объект.

Более конкретно, этот термин обычно относится к статическому методу, который возвращает экземпляр объявляющего его класса (либо прямой экземпляр, либо экземпляр подкласса). По моему опыту, есть несколько случаев, когда это особенно часто делается:

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

Итак, ваш пример на самом деле не включает «фабричный метод» ИМХО, но вы можете немного схитрить и описать getService() как один. (Скорее, я бы просто описал ServiceFactory как "фабрику", на этом не останавливаясь.) Преимущества ServiceFactory.getService() такие же, как и у фабричного метода, плюс обычные преимущества наличия вместо него экземпляра статического метода.

person ruakh    schedule 03.08.2016
comment
Следует всегда помнить, что метод Static Factory НЕ совпадает с шаблоном метода GoF Factory. Они совершенно разные. - person jaco0646; 04.08.2016
comment
@jaco0646: Ах, ты прав. Однако пример ОП, похоже, не является примером ни того, ни другого. - person ruakh; 04.08.2016
comment
Согласованный; термин фабрика часто используется очень расплывчато для описания любого метода создания. Затем эта расплывчатая терминология смешивается с GoF или другой терминологией, что приводит к путанице. - person jaco0646; 04.08.2016

Фабричный метод — это просто метод, который инкапсулирует создание объекта. Вместо использования оператора new, как обычно для создания вместо Service, в вашем примере вы используете фабричный метод для некоторого объекта.

ServiceFactory sf = new ServiceFactoryImpl();
// factory method
Service s = sf.getService();

Чтобы лучше проиллюстрировать роль метода, его можно было бы назвать createService. Теперь метод инкапсулирует детали создания Service, вы можете предоставить множество разновидностей методов (путем перегрузки), вы можете вернуть ему разные подклассы в зависимости от контекста или параметров, переданных фабричному методу.

person Arthur Noseda    schedule 03.08.2016