장점
👍 이름을 가질 수 있음
ex) 값이 소수인 BigInteger을 반환하는 함수는?
BigInteger(int, int, Random)
//or
BigInteger.probablePrime
이 것은 의미를 더 명확하게 전달할 수 있게 함(필자 의견)
👍 호출될 때마다 인스턴스를 새로 생성하지 않아도 됨
언제 어느 인스턴스를 살아 있게 할 지 철저히 통제할 수 있음
- imutable class 같은 경우 미리 만들거나, 인스턴스 캐싱 재활용 함 ex) Boolean.valueOf(boolean)
- 플라이웨이트 패턴과 비슷함
- 싱글턴, 인스턴스화 불가, 동치인 인스턴스가 하나뿐임을 보장 등 통제 가능함
- 불필요한 객체 생성을 피할 수 있음
👍 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있음
반환 객체 클래스를 자유롭게 선택 → “엄청난 유연성”
👍 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있음
반환 타입의 하위클래스이기만 하면 됨
ex)EnumSet의 경우 원소 개수에 따라 다른 하위 인스턴스를 반환함
추후에 반환 클래스가 변경되더라도 문제가 발생하지 않음
- 내부 동작의 변경이며, 반환타입의 하위 클래스이기 때문
👍 정적 팩터리 메서드를 작성하는 시점에서 반환할 객체의 클래스가 존재하지 않아도 됨
이 유연함은 프레임워크를 만드는 근간이 됨
클라이언트가 서비스 접근 API를 사용할 때 원하는 조건을 명시하여 반환받음
→ 필자 해석: 추가로 조건 - 하위 클래스 생긴다면 나중에 코드상으로 추가하면 됨 → 이 것은 메서드 작성 시점이 아니어도 된다는 뜻
- ex) java.util.ServiceLoader
단점
👎 상속하려면 public, protected 생성자 필요 → 없다면 하위클래스 못 만듬
상속보다 컴포지션 사용을 유도하고, 불변 타입으로 만들려면 이 제약을 지켜야하기때문에 오히려 장점이 될 수도 있음
👎 정적 팩터리 메서드를 프로그래머가 찾기 어려움
API 문서를 잘 쓰고, 알려진 규약을 따르는 것으로 문제를 완화하자!
정적 팩토리 메서드 네이밍 규약
from: 매개변수 하나 → 해당 타입 인스턴스 반환
of: 여러 매개변수 → 적합한 타입
valueOf: from과 of의 더 자세한 버전
instance or getInstance: 매개변수로 명시한 인스턴스 반환 but 같은 인스턴스 보장은 아님
create, newInstace: 새로운 인스턴스 생성 반환 보장
getType: getInstance와 같으나 다른 클래스에 팩토리메서드를 정의할 때 사용
ex) FileStore fs = Files.getFileStore(path)
newType: newInstance와 같지만 다른 클래스 반환일때
type: getType과 newType의 간결한 버전
요약:
정적 팩터리 메서드와 public 생성자는 각자의 쓰임새가 있으니 장단점을 고려해서 사용하자
무작정 public 생성자 제공 습관은 고쳐야한다!