Study/Effective Java

#1 생성자 대신 정적 팩터리 메서드를 고려하라

voider 2021. 3. 10. 15:12

Item #1 생성자 대신 정적 팩터리 메서드(static factory method)를 고려하라.

1. 이름을 가질 수 있다

생성자만으로 객체의 특성을 설명할 수 없다. 이름을 지을 수 있다면 객체의 특성을 좀 더 구체적으로 묘사할 수 있다.
BigInteger(int, int, Random) 보다 BigInteger.probablePrime 이 더 좋은 이름이다.

2.호출될 때마다 인스턴스를 생성하지 않아도 된다

불변 클래스는 인스턴스를 미리 만들어 두거나 새로 생성한 인스턴스를 캐싱하여 재활용하는 식으로 불필요한 객체 생성을 피할 수 있다. 생성 비용이 큰 객체라면 성능을 끌어올릴 수 있다.

반복되는 요청에 같은 인스턴스를 반환하는 식으로 정적 팩터리 방식은 언제 어느 인스턴스를 살아있게 할 것인지 제어할 수 있다. 이런 클래스를 인스턴스 통제(instance-controlled) 클래스라고 한다.

인스턴스 통제의 장점은 인스턴스화를 불가능하게 만들어 싱글톤으로 만들 수 있다. 따라서 그 클래스의 인스턴스는 모두 같다는 것을 보장할 수 있다는 것이다.

3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력

4. 입력 매개변수에 따라 다른 클래스의 객체를 반환할 수 있다.

세 번째 장점을 이용하여 매개변수에 따라 적절한 객체를 반환할 수 있다. 가령 EnumSet 클래스는 public생성자 없이 정적 팩터리 메서드만 제공한다. OPEN JDK에서 원소의 개수에 따라 두 가지 하위 클래스인 RegularEnumSet 또는 JumboEnumSet 의 인스턴스를 반환하는데, 클라이언트는 이 두 하위 타입의 존재를 모르고, 알 필요도 없다. JumboEnumSetLargeEnumSet 으로 바뀌더라도 클라이언트에는 아무런 영향이 없다.

5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.

이런 유연함은 서비스 제공자 프레임워크(service provider framework)를 만드는 근간이 된다. 제공자(provider)란 서비스의 구현체를 말한다. 대표적으로 JDBC가 있다.

정적 팩터리 메서드의 단점

  • 정적 팩터리 메서드만을 제공할 경우 상속이 불가능하다

  • 정적 팩터리 메서드는 프로그래머가 찾기 어렵다
    때문에 어떻게 인스턴스를 얻어야 하는 지 API문서를 읽어야 한다.
    정적 팩터리 이름에는 몇 가지 알려진 규약이 있다.

    • from : 매개 변수를 하나 받아서 해당 타입의 인스턴스를 반환하는 형변환 메서드
      Data.from(instance)
    • of : 여러 매개변수를 바당서 적합한 타입의 인스턴스를 반환하는 집계 메서드
      EnumSet.of(JACK, QUEEN, KING)
    • valueOf : from과 of의 더 자세한 버전
      BigInteger.valueOf(Integer.MAX_VALUE)
    • getInstance,create,getType,newType,type등

정적 팩터리 메서드와 public생성자는 각자의 쓰임새가 있으니 장단점을 이해하고 사용해야 한다. 정적 팩터리를 사용하는 것이 유리한 경우가 많으므로 무작정 public생성자를 제공하던 버릇이 있다면 고쳐야 한다