Когда использовать конструктор и когда использовать метод getInstance () (статические заводские методы)?

  1. Когда и как мы должны использовать конструктор

    Foo bar = new Foo(); 
  2. И когда и как мы должны использовать getInstance () (статические заводские методы)

     Foo bar = Foo.getInstance(); 

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

Кажется, что все сосредоточены на одиночных играх, в то время как я думаю, что речь идет о конструкторе и статических заводских методах .

Это на самом деле пункт 1: рассмотрим статические заводские методы вместо конструкторов эффективной Java от Джошуа Блоха:

Пункт 1: Рассмотрите статические заводские методы вместо конструкторов

Обычный способ для classа, позволяющий клиенту получить экземпляр сам по себе, – это предоставить публичный конструктор. Существует еще одна методика, которая должна быть частью инструментария каждого программиста. Класс может предоставлять общеansible статический заводский метод , который представляет собой просто статический метод, возвращающий экземпляр classа. Вот простой пример из Boolean (примитивный class в штучной упаковке для примитивного типа boolean ). Этот метод переводит логическое примитивное значение в ссылку на Boolean :

 public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } 

Обратите внимание, что статический заводский метод не совпадает с шаблоном Factory Method из шаблонов проектирования [Gamma95, p. 107]. Статический заводский метод, описанный в этом элементе, не имеет прямого эквивалента в шаблонах проектирования .

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

Преимущества (цитирование книги):

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

Недостатки (по-прежнему цитируют книгу):

  • Основным недостатком предоставления только статических заводских методов является то, что classы без публичных или защищенных конструкторов нельзя подclassифицировать.
  • Вторым недостатком статических заводских методов является то, что они не могут быть легко различимы с другими статическими методами.

У вас есть два вопроса: когда я должен вызвать метод getInstance() и когда его следует создать ?

Если вы решаете, следует ли вызвать метод getInstance() , это легко. Вам просто нужно прочитать документацию по classу, чтобы узнать, когда вы должны это назвать. Например, NumberFormat предоставляет конструктор и метод getInstance() ; метод getInstance() даст вам локализованный NumberFormat . С другой стороны, для Calendar конструктор защищен. Вы должны вызвать getInstance() чтобы получить его.

Если вы решаете, нужно ли создавать метод getInstance() , вам нужно решить, что вы пытаетесь выполнить. Либо вы не хотите, чтобы люди вызывали ваш конструктор (вы создаете синглтон или фабрику ), либо вы не возражаете (как в NumberFormat выше, где они инициализируют некоторые объекты для удобства вызывающего абонента).


Короче? Не беспокойтесь о создании методов getInstance() в вашем собственном коде. Если время возникает, когда они будут полезны, вы узнаете. И вообще, если вы можете вызвать конструктор classа, вы, вероятно, должны это делать, даже если class предоставляет метод getInstance() .

Использование методов getInstance:

  • Если вы хотите контролировать / ограничивать строительство, например, Singleton
  • реализовать Factory pattern, например DriverManager.getConnection
  • Если вы хотите лучше указать , как создается экземпляр (конструкторы должны иметь то же имя, что и имя classа), ознакомьтесь с методами фабрики NumberFormat getCurrencyInstance , getIntegerInstance и другими примерами.

Но большую часть времени ваш объект будет простым POJO, а использование публичных конструкторов – наиболее практичное и очевидное решение.

U1: getInstance из другого classа

Чтобы вернуть экземпляр другого classа:

 public class FooFactory { public static Foo getInstance() { return new Foo(); } } 

Методы NumberFormat.getInstance делают это, поскольку они фактически возвращают экземпляры DecimalFormat .

U2: проблемы с Singleton

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

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

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

Используйте первое, чтобы создать несколько объектов classа.

НО не давайте вашему classу обе возможности.

Соблюдайте осторожность, чтобы не переубеждать одиночные игры, используйте их только в том случае, если в системе существует только один экземпляр, иначе вы ограничили бы возможности повторного использования вашего classа в других проектах. Это звучит интересно, чтобы иметь возможность вызвать getInstance со всего мира в вашем проекте, но это не ясно, кто на самом деле владеет этим экземпляром: никто и / или все. Если у вас много одиночных игр в проекте, вы можете поспорить, что система плохо разработана (обычно). Синглтоны должны использоваться с осторожностью, применяется тот же совет, что и для глобальных переменных.

Один случай, когда я всегда предпочитаю статическую фабрику над обычным конструктором, – это когда я знаю, что конструкция объекта будет медленной. Я делаю простую инициализацию на конструкторе, но если мне нужно создать что-то тяжелое, я буду использовать статический метод и документирую поведение.

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

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

  • Должен ли я инициализировать переменную внутри конструктора или внешнего конструктора
  • Преобразование объекта в JSON на Android
  • java.net.UnknownHostException: Невозможно разрешить хост «»: нет адреса, связанного с именем хоста, и Конец ввода с символом 0
  • Как передать объект из одного действия в другое на Android
  • Почему получение Google Directions для Android с использованием данных KML больше не работает?
  • Импорт внешнего файла .jar в проект Android
  • Лучше ли использовать System.arraycopy (...), чем цикл for для копирования массивов?
  • Pixel-Perfect Collision Detection Android
  • Ориентация изображения - Android
  • Bitmap getWidth возвращает неверное значение
  • Более эффективный способ для цикла паузы
  • Давайте будем гением компьютера.