публичный статический метод фабрики - PullRequest
20 голосов
/ 02 ноября 2010

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

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

Спасибо.

Ответы [ 5 ]

11 голосов
/ 02 ноября 2010

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

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

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

Да, это один из способов, которым это можно сделать.Но на самом деле все возможно.

5 голосов
/ 02 ноября 2010

Прежде всего, спасибо вам за ваш выбор в освещении Java: книга Блоха - это превосходный учебник.

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

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

public class Money { 

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

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

}

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

public ResourceManager {

    private final static ResourceManager me = new ResourceManager();

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

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

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


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

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 );

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

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

2 голосов
/ 02 ноября 2010

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

1 голос
/ 02 ноября 2010

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

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

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

в отличие от конструкторов, статические фабричные методы не требуются для создания нового объекта каждый раз, когда они вызываются

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

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

0 голосов
/ 02 ноября 2010

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

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

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

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

...