Когда использовать конструктор, а когда использовать метод getInstance () (статические фабричные методы)? - PullRequest
78 голосов
/ 03 июля 2010
  1. Когда и как мы должны использовать Конструктор

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

    Foo bar = Foo.getInstance();
    

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

Ответы [ 6 ]

90 голосов
/ 03 июля 2010

Кажется, что все сосредотачиваются на синглетах, хотя я думаю, что вопрос на самом деле о конструкторе против статических фабричных методов .

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

Элемент 1:Рассмотрим статические фабричные методы вместо конструкторов

Нормальный способ для класса, позволяющий клиенту получить собственный экземпляр, - предоставить открытый конструктор.Есть еще один метод, который должен быть частью инструментария каждого программиста.Класс может предоставить открытый статический метод фабрики , который является просто статическим методом, который возвращает экземпляр класса.Вот простой пример из Boolean (класс примитива в штучной упаковке для типа примитива boolean).Этот метод преобразует логическое значение примитива в Boolean ссылку на объект:

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

Обратите внимание, что статический метод фабрики не совпадает с шаблоном Factory Method из DesignУзоры [Гамма95, с.107].Статический метод фабрики, описанный в этом пункте, не имеет прямого эквивалента в Шаблоны проектирования .

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

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

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

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

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

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

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

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


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

7 голосов
/ 03 июля 2010

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

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

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

U1: получить экземпляр из другого класса

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

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

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

U2: одиночные проблемы

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

6 голосов
/ 03 июля 2010

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

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

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

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

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

1 голос
/ 11 мая 2012

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

0 голосов
/ 03 июля 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...