Выполняет ли Class.newInstance() шаблон шаблона "Абстрактный factory"?

Я начал читать Джошуа Блоха "Эффективная Java" (второе издание). При чтении пункта 2 (Рассмотрим конструктор, столкнувшись со многими параметрами конструктора), существует конкретное утверждение, которое автор делает w.r.t методом Class.newInstance(). В частности, автор говорит, что

Традиционная абстрактная реализация Factory в Java была объектом "Class", а метод "newInstance" играл роль метода "build".

Эта часть меня немного смутила - мое понимание абстрактного шаблона дизайна Factory заключается в том, что он используется для представления Factory заводов. Метод Class.newInstance(), на мой взгляд, больше ограничивает "философию кодирования статического Factory метода (который, кстати, является пунктом 1 в той же книге)

Мысли, кто-нибудь? Я очень старался взломать несколько сложных интервью и был бы очень признателен, если бы мои основы были твердыми, прежде чем появляться для таких интервью.

Спасибо.

Ответ 1

Вот мое мнение.

Прежде всего, шаблон Abstract Factory не предназначен для Factory заводов. Ключевым аспектом этого шаблона является доступный интерфейс с базовой (возможно, недоступной) реализацией Factory, благодаря которой вы можете получить доступные интерфейсы (возможно, недоступных) реализаций объектов. Я знаю, это длинный неприятный игровой процесс, когда я понимаю некоторые условия применимости этого шаблона в книге Гамма:

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

В конце вы получаете объекты, а не фабрики.

Во-вторых, я бы не стал устанавливать отношения 1:1 между концепциями шаблонов и языковыми ключевыми словами. "Аннотация Factory" необязательно всегда переводится в конструкции Java abstract class или interface. У вас все еще может быть обычный, расширяемый, мгновенный класс, который представляет собой "Abstract Factory", если вы каким-то образом гарантируете, что клиентский код не зависит от базовых Factory и реализаций объектов. Это случай java.lang.Class, который не является абстрактным и не является интерфейсом, но выполняет ли задание скрытие реализации конструктора без параметров без использования метода newInstance(). Вероятно, это яснее, если вы используете его как:

Object o = Class.forName(type).newInstance();

Class воспроизводит "Abstract Factory", а Object воспроизводит "абстрактный продукт" для реализации типа.

Наконец, newInstance() не является статическим Factory методом, я думаю, потому что этот шаблон предназначен для возврата экземпляров класса, на котором он реализован. newInstance() не возвращает экземпляры Class и sub Class es. Он возвращает экземпляры того типа, который он представляет. Он также не является "методом Factory", как утверждает Блох в своей книге.

Ответ 2

Я не думаю, что что-либо предполагает, что Abstract Factory является "a w770 > заводов". AbstractFactory<T> не создает фабрики, создающие T s, он создает T напрямую.

Идея, что она абстрактна, позволяет логике создавать T для ввода. Например, вы могли бы:

public interface ConnectionFactory {
    Connection newConnection();
}

//passed to your object normally:
public class RealConnectionFactory implements ConnectionFactory {
    //...
}

//passed to your object when unit testing:
public class FakeConnectionFactory implements ConnectionFactory {
    //...
}

//...

public class MyDao {
   public MyDao(ConnectionFactory connectionFactory) {
       this.conn = connectionFactory.newConnection();
   }
}

В этом случае ConnectionFactory создает Connection s, но является абстрактным, потому что это интерфейс.

Я с тобой согласен, что Class<?>.newInstance() не является каноническим примером абстрактного factory, потому что Class не является абстрактным, и на самом деле он не может быть расширен. Вы не можете запросить Class<Integer> и иметь одну реализацию, инициализирующую новое значение 1, а другое инициализировать новое значение 7.

Однако вы могли бы растянуть вещи, сказав что-то вроде Class<? extends InputStream> является абстрактным Factory of InputStream s, с конкретными реализациями Class<SocketInputStream> и Class<FileInputStream>. Это не традиционный смысл "абстрактного" (хотя есть еще один класс: Class).

Но даже тогда это бесполезно как абстрактный factory, потому что способ, которым вы реализуете новую конкретную версию "factory", - это создать новый класс, который расширяет InputStream. Это вряд ли относится к тем, что предназначены для заготовок.

Ответ 3

По-моему, он имеет в виду код, например:

Integer.class.newInstance();

Где Class<T> - абстрактный factory. Это стало конкретным, когда вы передали параметр типа, например. Integer. Затем вы вызываете "строитель", newInstance().