Выполняет ли 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()
.