Статические методы фабрики по сравнению с Instance (нормальные) конструкторы?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

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

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

47
задан Jon Skeet 8 July 2016 в 20:47
поделиться

9 ответов

В Эффективный Java, 2-й выпуск , Joshua Bloch, конечно, рекомендует первому. Существует несколько причин, которые я могу помнить, и несомненно некоторые, которые я не могу:

  • можно дать методу понятное имя. Если у Вас есть два способа создать экземпляр, оба из которых берут интервал, но имеют различные значения для того интервала, использование нормального метода делает код вызова намного более читаемым.
  • заключение А первого - у Вас могут быть различные методы фабрики с тем же списком параметров
  • , можно возвратить пустой указатель для случаев "потенциально ожидаемого отказа", тогда как конструктор будет всегда или возвращать значение, или выдавать исключение
  • можно возвратить тип кроме заявленного (например, возвратить производный класс)
  • , можно использовать его в качестве фабрики, для потенциального возврата ссылки на тот же объект несколько раз

оборотные стороны:

  • Это не столь идиоматично, в настоящее время - разработчики больше привыкли к наблюдению "нового"
  • , Если Вы видите "новый", Вы знаете , Вы получаете новый экземпляр (по модулю причуда, которую я недавно упомянул )
  • , необходимо сделать соответствующих конструкторов доступными для подклассов
  • В C# 3, вызовы конструктора в состоянии установить поля/свойства компактным способом с объектными выражениями инициализатора; функция не относится к вызовам статического метода
55
ответ дан Community 26 November 2019 в 19:27
поделиться

Я пишу конструктору, когда создание экземпляра не имеет никаких побочных эффектов, т.е. когда единственная вещь, которую делает конструктор, инициализирует свойства. Я пишу статический метод (и делаю конструктора частным), если создание экземпляра делает что-то, что Вы обычно не ожидали бы, что конструктор сделает.

, Например:

public class Foo
{
   private Foo() { }

   private static List<Foo> FooList = new List<Foo>();
   public static Foo CreateFoo()
   {
      Foo f = new Foo();
      FooList.Add(f);
      return f;
   }
}

, поскольку я придерживаюсь этого соглашения, если я вижу

Foo f = Foo.CreateFoo();
Bar b = new Bar();

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

22
ответ дан Robert Rossney 26 November 2019 в 19:27
поделиться

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

9
ответ дан Dan Goldstein 26 November 2019 в 19:27
поделиться

Существует статья от ICSE '07, который изучил удобство использования конструкторов по сравнению с шаблонами "фабрика". В то время как я предпочитаю шаблоны "фабрика", исследование показало, что разработчики были медленнее в нахождении корректного метода фабрики.

http://www.cs.cmu.edu/~NatProg/papers/Ellis2007FactoryUsability.pdf

7
ответ дан Uri 26 November 2019 в 19:27
поделиться

Статический метод. Тогда можно возвратить пустой указатель, вместо того, чтобы выдать исключение (если ссылочный тип)

2
ответ дан Darren Kopp 26 November 2019 в 19:27
поделиться

Я предпочитаю конструктор экземпляра, просто потому что это имеет больше смысла мне, и существует менее потенциальная неоднозначность с тем, что Вы пытаетесь выразить (т.е.: что, если FromCharacters является методом, который берет отдельный символ). Конечно, субъективный, все же.

2
ответ дан Nick 26 November 2019 в 19:27
поделиться

Я лично предпочитаю видеть нормального конструктора, так как конструкторы должны использоваться для построения. Однако, если существует серьезное основание к не , используют один, т.е. если бы FromCharacters явно заявил, что это не выделило новую память, это стоило бы. "Новое" в вызове имеет значение.

2
ответ дан nimish 26 November 2019 в 19:27
поделиться

Это зависит. Для языков, на которых использование конструктора экземпляра "нормально", я обычно использовал бы тот, если у меня не было серьезного основания не к. Это следует за принципом наименьшего количества удивления.

Между прочим, Вы забыли другой общий падеж: пустой указатель/конструктор по умолчанию соединяется с методом инициализации.

2
ответ дан ejgottl 26 November 2019 в 19:27
поделиться

Поскольку Jon Skeet перефразировал Josh Bloch, существует много причин, почему статический метод фабрики предпочтителен для конструктора во многих случаях. Я сказал бы, что, если класс является простым без дорогой установки или сложного использования, останьтесь с идиоматическим конструктором. Современные JVMs делают создание объекта чрезвычайно быстрым и дешевым. Если класс мог бы быть разделен на подклассы, или Вы в состоянии сделать его неизменным (большое преимущество для параллельного программирования, которое только собирается стать более важным), то пойдите с методом фабрики.

Еще одна подсказка. Не называйте метод фабрики Foo.new* или Foo.create*. Метод с этими именами должен всегда возвращать новый экземпляр, и выполнение так пропускает одно из больших преимуществ метода фабрики. Лучшее соглашение о присвоении имен Foo.of* или Foo.for*. Библиотека Google Guava (раньше Google Collections Library ) делает отличную работу по этому, по моему скромному мнению.

1
ответ дан Fruny 26 November 2019 в 19:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: