본문 바로가기
책 정리/이펙티브 자바

[이펙티브 자바] 생성자 대신 정적 팩터리 메서드를 고려할 것 - item 1

by chanwoodev 2023. 6. 18.

장점


👍 이름을 가질 수 있음

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 생성자 제공 습관은 고쳐야한다!