그 클래스의 인스턴스를 반환하는 단순한 정적 메서드를 말한다.
➕ 참고
정적 팩터리 메서드는 디자인 패턴에서의 팩터리 메서드 (Factory Method)와 다르다. 디자인 패턴 중 이와 일치하는 패턴은 없다.
생성자에 넘기는 매개변수와 생성자 자체만으로는 반환될 객체의 특성을 제대로 설명하지 못한다.
반면, 정적 팩터리 메서드는 이름만 잘 지으면 반환될 객체의 특성을 쉽게 묘사할 수 있다.
BigInteger(int, int, Random)
vs BigInteger.probablePrime
'값이 소수인 BigInteger를 반환한다'는 의미를 어느 쪽이 더 잘 설명하고 있는지는 누구나 알 것이다.
같은 객체가 자주 요청되는 상황이라면 성능을 상당히 끌어올려 준다.
플라이웨이트 패턴도 이와 비슷한 기법이라 할 수 있다.
이 능력은 반환할 객체의 클래스를 자유롭게 선택할 수 있게 하는 '엄청난 유연성'을 선물한다.
반환 타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관없다.
심지어 다음 릴리스에서, 또 다른 클래스의 객체를 반환해도 된다.
이런 유연함은 서비스 제공자 프레임워크(대표적으로 JDBC가 있다)를 만드는 근간이 된다.
컬렉션 프레임워크의 유틸리티 구현 클래스들은 상속할 수 없다.
그러나 이 제약은 상속보다 컴포지션을 사용하도록 유도하고 불변 타입으로 만들려면 이 제약을 지켜야 한다는 점에서 오히려 장점으로 받아들일 수도 있다!
생성자처럼 API 설명에 명확히 드러나지 않으니 사용자는 정적 팩터리 메서드 방식 클래스를 인스턴스화할 방법을 알아내야 한다.
from
: 매개변수를 하나 받아서 해당 타입의 인스턴스를 반환하는 형변환 메서드
Date d = Date.from(instant);
of
: 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
valueOf
: from과 of의 더 자세한 버전
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
instance
혹은 getInstance
: 매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지는 않는다.
StackWalker luke = StackWalker.getInstance(options);
create
혹은 newInstance
: instance 혹은 getinstance와 같지만, 매번 새로운 인스턴스를 생성해 반환함을 보장한다.Object newArray = Array.newInstance(classObject, arrayLen);
getType
: getInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 사용한다. Type
은 팩터리 메서드가 반환할 객체의 타입이다.
FileStore fs = Files.getFileStore(path);
newType
: newInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 사용한다. Type
은 팩터리 메서드가 반환할 객체의 타입이다.
BufferedReader br = Files.newBufferedReader(path);
type
: getType과 newType의 간결한 버전 List<Complaint> litany = Collections.list(legacyLitany);
📌 핵심 정리
정적 팩터리 메서드와 public 생성자는 각자의 쓰임새가 있으니 상대적인 장단점을 이해하고 사용하는 것이 좋다.
그렇다고 하더라도 정적 팩터리를 사용하는게 유리한 경우가 더 많다..
무작정 public 생성자를 제공하던 습관이 있다면 고치자!