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

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

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

    Foo bar = Foo.getInstance();
    

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

Ответ 1

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

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

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

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

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

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

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

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

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

Недостатки (цитирование книги):

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

Ответ 2

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

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

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


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

Ответ 3

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

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

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

U1: getInstance из другого класса

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

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

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

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

Ответ 6

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

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