Этот подход называется статическим фабричным шаблоном.Для этого есть ряд причин, и вот некоторые из известных мне причин:
Легче читать / использовать
Взяв java.time.Duration
в качестве примера, вы заметите,что этот класс также имеет приватный конструктор.Вы также заметили бы методы, такие как Duration.ofDays()
, Duration.ofHours()
и т. Д.
Если этот класс должен предоставить свой конструктор (сделать его общедоступным), то вы ожидаете что-то вроде:
public Duration(long days, long hours, long minutes, long seconds, long milliseconds, long nanoseconds)
Делать это было бы очень хлопотно, потому что большинство людей не создают длительности типа «1 день 2 часа 3 минуты, 4 секунды, 5 миллисекунд и 6 наносекунд».
Абстрагирование реализации
Это на самом деле главная причина для ByteBuffer
использования этого подхода.ByteBuffer
сам по себе является классом abstract
.Существует несколько классов реализации, но он был скрыт от своих пользователей.ByteBuffer.allocate()
фактически возвращает экземпляр DirectByteBuffer
, но вы даже не знаете, DirectByteBuffer
даже существовал!Это связано с тем, что сам этот класс является частным для пакета.
Кэширование
Некоторые API могут внутренне выполнять некоторое кэширование, чтобы не создавать избыточную копию одной и той же вещи.Это обычно происходит в неизменяемых классах, где значение остается неизменным.Статические «творческие» методы позволяют классу искать кэшированный экземпляр для возврата вызывающей стороне, вместо того, чтобы разрешить вызывающей стороне создавать его чрезмерные экземпляры.Другим вариантом использования может быть попытка повторно использовать объект, который будет дорогостоящим для повторного создания.
Частично final
Некоторые API могут пытаться достичь чего-то похожего на final
классы.
package com.test
public class Test {
Test() { // package-private
}
public Test create() { return new Test(); }
}
Это позволяет API создавать новые классы, расширяющие этот класс Test
, в то же время блокируя других людей от создания подклассов Test
.Это связано с тем, что подклассы вне пакета com.test
не смогут вызывать super()
.
Однако в этом больше нет необходимости после введения модулей в Java 9.