Подтвердить что ты не робот

Открытый статический метод factory

Прежде всего, пожалуйста, простите меня, если это действительно тупой вопрос, я просто пытаюсь выучить этот язык в своем ядре. Я читаю "Эффективная Java" и в первой главе рассказывается о методах Static factory и конструкторах. Их плюсы и минусы. Немногие вещи, которые меня смущают:

  • класс объекта, возвращаемого статическим factory методом, является непубличным - что именно это означает?
  • В отличие от конструкторов статические методы factory не требуются для создания нового объекта при каждом вызове. Как это происходит? Я вызываю метод factory только для получения нового объекта, и мы помещаем проверку в метод factory для проверки того, существует ли объект?

Спасибо.

4b9b3361

Ответ 1

класс объекта, возвращаемого статическим методом factory, является непубличным - что именно это означает?

Это означает, что фактический класс объектов, возвращаемых статическим factory методом, может быть подклассом объявленного типа, и этот подкласс не должен быть общедоступным. Это просто еще одна деталь реализации, которой клиентский код не должен заботиться.

В отличие от конструкторов статические методы factory не требуются для создания нового объекта каждый раз > время их вызова - как это происходит? Я вызываю метод factory только для получения нового объекта и мы помещаем проверку в метод factory для проверки того, существует ли объект?

Да, это можно сделать так. Но на самом деле все возможно.

Ответ 2

Во-первых, к вам по вашему выбору в Java-lit: книга Блоха - превосходный учебник.

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

Например, предположим, что у вас действительно простой класс значений типа Money. Ваш статический метод factory, вероятно, должен возвращать новый экземпляр - то есть новый объект с определенным значением для денег. Итак, вот так:

public class Money { 

    private Money(String amount) { ... } /* Note the 'private'-constructor */

    public static Money newInstance(String amount) {
        return new Money(amount);
    }

}

Но скажем, у вас есть объект, который управляет некоторым ресурсом, и вы хотите синхронизировать доступ к этому ресурсу через некоторый класс ResourceManager. В этом случае вы, вероятно, хотите, чтобы ваш статический метод factory возвращал один и тот же экземпляр для себя всем - заставляя всех проходить через тот же самый экземпляр, чтобы этот экземпляр 1 мог управлять процессом. Это следует за одноточечным шаблоном. Что-то вроде этого:

public ResourceManager {

    private final static ResourceManager me = new ResourceManager();

    private ResourceManager() { ... } /* Note the 'private'-constructor */

    public static ResourceManager getSingleton() {
        return ResourceManager.me;
    }
}

Вышеупомянутый метод заставляет пользователя использовать только один экземпляр, позволяя точно контролировать, кто (и когда) имеет доступ к тому, что вы управляете.


Чтобы ответить на ваш первый вопрос, рассмотрите это (по общему признанию, не лучший пример, он довольно ad-hoc):

public class Money {

    private Money(String amount) { ... }


    public static Money getLocalizedMoney( MoneyType localizedMoneyType, String amount ) { 
        switch( localizedMoneyType ) {
            case MoneyType.US:
                return new Money_US( amount );
            case MoneyType.BR:
                return new Money_BR( amount );
            default:
                return new Money_US( amount );
        }
    }
}

public class Money_US extends Money { ... }

public class Money_BR extends Money { ... }

Обратите внимание, как я могу это сделать:

Money money = Money.getLocalizedMoney( user_selected_money_type );
saveLocalizedMoney( money );

Опять же, действительно надуманный пример, но, надеюсь, он поможет вам увидеть более или менее то, что Блох получал с этой точкой.

Другие ответы были хорошими - я просто думаю, что, как новичок, иногда это помогает увидеть некоторый фактический код.

Ответ 3

Когда вы используете ключевое слово new, тогда вы, как разработчик, знаете, что JDK создаст новый экземпляр этого объекта. Что говорит автор, когда вы используете статический метод, разработчик больше не знает, создает ли метод новый экземпляр или, возможно, делает что-то еще. Что-то еще может быть, повторное использование кэшированных данных, объединение объектов, создание частной реализации и возврат подкласса класса.

Ответ 4

класс объекта, возвращаемого статическим методом factory, является непубличным

Часто статический метод factory возвращает либо объект, типизированный как интерфейс (наиболее распространенный), либо иногда некоторый базовый класс (менее распространенный). В любом случае вы не знаете точный класс возвращаемого объекта.

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

В отличие от конструкторов статические методы factory не требуются для создания нового объекта при каждом вызове

Чтобы понять это, рассмотрим случай работы с одноэлементным. Вы можете вызвать .getInstance() в некоторых классах factory, чтобы получить экземпляр singleton для определенного объекта. Обычно это создает экземпляр объекта, если он еще не существует, или дает вам существующий экземпляр, если он уже выполняется. В любом случае вы возвращаете копию объекта. Но вы не знаете (и не будете) знать, должен ли этот синглтон быть создан, или если он уже был создан ранее.

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

Ответ 5

На оба ваших вопроса можно ответить, посмотрев на некоторый код, который использует оба этих свойства статических методов factory. Я предлагаю посмотреть на Guava ImmutableList.

Обратите внимание, что метод no-arg factory of() всегда возвращает один и тот же экземпляр (он не создает новый экземпляр каждый раз). Если вы посмотрите внимательно, вы также заметите, что его метод copyOf(Iterable) factory фактически возвращает объект, который передается ему, если этот объект сам является ImmutableList. Оба эти преимущества используют тот факт, что ImmutableList гарантированно не изменится.

Обратите внимание также, как различные методы factory в нем возвращают разные подклассы, такие как EmptyImmutableList, SingletonImmutableList и RegularImmutableList, не подвергая опасности типы этих объектов. Подписи метода просто показывают, что они возвращают ImmutableList, и все подклассы ImmutableList имеют видимость в виде пакета (по умолчанию), что делает их невидимыми для пользователей библиотеки. Это дает все преимущества нескольких классов реализации без добавления каких-либо сложностей с точки зрения пользователя, поскольку им разрешено просматривать только ImmutableList как один тип.

В дополнение к ImmutableList, большинство экземпляров класса Guava используют статические методы factory. Гуава также иллюстрирует множество принципов, изложенных в "Эффективной Java" (не удивительно, учитывая, что он был разработан этими принципами и с руководством самого Джоша Блоха), поэтому вы можете счесть его более полезным взглянуть на него, работая через книгу.