Лучшая практика Java: new vs .create ()

Ну, у меня очень концептуальный вопрос. Многие вещи выглядят как ткани, и я не уверен, в чем заключается большая выгода. Как пример

public class MyObject {
public MyObject() {

}
public static MyObject create() {
    return new MyObject();
}

public void doSomething(){
    // some code...
};

}

Единственное преимущество, с моей точки зрения, - это меньшая ставка на код. На мой взгляд, никакого влияния на производительность не происходит. Есть ли другие преимущества?

MyObject myobject = new MyObject();

or

MyObjecct myobject = MyObject.create();

Спасибо


person MemLeak    schedule 26.06.2013    source источник
comment
create должен быть статическим в вашем примере.   -  person Averroes    schedule 26.06.2013
comment
@Averroes, конечно, спасибо - исправил   -  person MemLeak    schedule 26.06.2013
comment
Также посмотрите здесь: stackoverflow.com/questions/3169372/   -  person Averroes    schedule 26.06.2013


Ответы (6)


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

В общем, если вы используете статическую функцию создания, вы должны объявить конструктор закрытым, таким образом гарантируя, что ваши пользователи могут создавать ТОЛЬКО объекты с помощью статической функции.

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

Однако в некоторых случаях я считаю, что статический конструктор полезен:

  1. Для создания больших сложных объектов, особенно объектов, требующих большой сложности при инициализации - часто простой конструктор вводит пользователей библиотеки в заблуждение, полагая, что задача построения выполняется быстро и легко.
  2. Если у вас есть несколько конструкторов с неоднозначными параметрами, вы можете использовать имя статической функции, чтобы сделать ее более читаемой, например, у вас могут быть createFromFile (String FileName) и createFromJSONEncoding (String Data)
  3. Вы хотите контролировать, создается ли ДЕЙСТВИТЕЛЬНО новый объект - например, если это ресурс только для чтения, вы можете держать буфер ресурсов уже открытым, и если пользователь библиотеки запрашивает тот же ресурс дважды, вы можете просто дать им уже кэшированная копия (в отличие от создания новой дублирующей копии)
person Elemental    schedule 26.06.2013

Джошуа Блох рассматривает эту проблему в Эффективной Java, Глава 2, Пункт 1. Рассмотрите статические фабричные методы вместо конструкторов; вот несколько основных моментов:

  • «Одно из преимуществ статических фабричных методов состоит в том, что, в отличие от конструкторов, у них есть имена». - у вас не может быть двух разных конструкторов, принимающих аргумент int, но у вас может быть два статических фабричных метода с именами createWithAge(int age) и createWithHeight(int height)
  • «Второе преимущество статических фабричных методов состоит в том, что, в отличие от конструкторов, от них не требуется создавать новый объект при каждом вызове».
  • «Третье преимущество статических фабричных методов состоит в том, что, в отличие от конструкторов, они могут возвращать объект любого подтипа своего возвращаемого типа».

Как видите, проблема связана не с производительностью (за исключением повторного использования кешированных экземпляров), а в основном с объектно-ориентированным дизайном.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Ой, я только что увидел тот же ответ (гораздо лучше объясненный), уже опубликованный для другого вопроса: https://stackoverflow.com/a/3169644/262683. Виноват...

person Costi Ciudatu    schedule 26.06.2013

На этот вопрос нет ответа.

Дело в том, что оба шаблона являются законными способами создания объектов, применимых к конкретным ситуациям.

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

Новый оператор удобен своей простотой и довольно важен для классов, которые предназначены для наследования.

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

Предлагаю закрыть этот вопрос.

person scottb    schedule 26.06.2013
comment
-1 Вы намекаете, что есть ответ «что лучшая практика зависит от ваших целей», отказываетесь объяснять этот ответ - а затем говорите спрашивающему, что это плохой вопрос. Если вы так считаете, вы должны просто проголосовать за вопрос, если у вас нет представителя, который мог бы проголосовать за закрытие. - person Elemental; 26.06.2013
comment
@Elemental: Хорошо, итак ... какая часть статических фабричных методов важна, например, управление экземпляром ... и ... new подходит для классов, предназначенных для наследования, не похоже на объяснение для вас? - person scottb; 04.07.2013

Я вижу случай, когда вам может понадобиться использовать create:

Вы должны контролировать создание каждого экземпляра вашего класса. Например, вы подсчитываете количество созданных объектов или каким-то образом связываете их, и если количество экземпляров достигло желаемого максимального исключения, исключение.

Также может быть интересно прочитать о шаблоне фабрики.

Если вы не уверены, просто создайте через new

И если вы решите использовать create, вы, вероятно, захотите сделать свой конструктор закрытым.

person Tala    schedule 26.06.2013
comment
Конструктор также может вызывать исключение. - person Sotirios Delimanolis; 26.06.2013
comment
конечно, я имел в виду, что он проверяет некоторые ограничения и выдает исключение - person Tala; 26.06.2013
comment
Чем это отличается от того, что вы можете делать в конструкторе? - person Sotirios Delimanolis; 26.06.2013
comment
вы можете делать все, что хотите, это просто сохраняет код более чистым и читаемым - person Tala; 26.06.2013

Это (упрощенный) Factory Pattern. Пожалуйста, проверьте раздел применимости статьи в Википедии, чтобы узнать, где она используется.

person Bruno Grieder    schedule 26.06.2013

Теперь, когда у вас нет другого класса для создания объекта вашего класса, вы делаете свой конструктор класса закрытым:

private MyObject()

теперь любой класс, желающий создать ваш объект класса, должен будет сделать это:

MyObjecct myobject = MyObject.create();

Потому что теперь выполнение этого внутри другого класса MyObject myobject = new MyObject(); вызовет ошибку компилятора.

person Abubakkar    schedule 26.06.2013