💡 Effective Java 공부
클래스는 생성자와 별도로 정적 팩토리 메소드(static factory method)를 제공할 수 있다.
이 정적 팩토리 메소드는 디자인 패턴의 팩토리 메소드와 다르다.
public static Boolean valueOf(boolean b){
return b ? Boolean.TRUE : Boolean.FALSE;
}
위 메소드는 기본 타입인 boolean
을 받아 Boolean
객체 참조로 변환해 준다.
정적 팩토리 메소드가 생성자보다 좋은 장점을 찾아보면
생성자에 넘기는 매개변수만으로는 반환될 객체의 특성을 제대로 설명할 수 없다. 반면 정적 팩토리 메소드는 이름을 통해 반환될 객체의 특성을 묘사할 수 있다.
한 클래스에 시그니처가 같은 생성자가 여러 개 필요할 것 같으면, 생성자를 정적 팩토리 메소드로 바꾸고 각각의 차이를 드러내는 이름을 지어주는게 좋다.
불변 클래스는 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱하여 재활용 하는 식으로 불필요한 객체 생성을 피할 수 있다. 같은 객체가 자주 요청되는 상황에서 성능을 끌어올릴 수 있다.
정적 팩토리 방식의 클래스는 언제 어느 인스턴스를 살아 있게 할지 통제할 수 있다. 이런 클래스를 인스턴스 통제 클래스
라고 한다.
인스턴스를 통제하는 이유는 무엇일까?
인스턴스를 통제하면 클래스를 싱글톤
으로 만들 수도, 인스턴스화 불가
로 만들 수 도있다. 또한 불변 값 클래스에서 동치인 인스턴스가 단 하나임을 보장할 수 있다. (a==b일 때만 a.equals(b)
가 성립)
반환할 객체의 클래스를 자유롭게 선택할 수 있는 유연성
을 보장한다.
API를 만들 때 이를 응용하면 구현 클래스를 공개하지 않고도 그 객체를 반환할 수 있어 API를 작게 유지할 수 있다.
이는 인터페이스를 정적 팩토리 메소드의 반환 타입으로 사용하는 인터페이스 기반 프레임워크를 만드는 핵심이기도 하다.
반환 타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관없다.
EnumSet
클래스는 public 생성자 없이 오직 정적 팩토리만 제공하는데 OpenJDK에서는 원소의 수에 따라 두 가지 하위 클래스(RegularEnumSet
, JumboEnumSet
) 중 하나의 인스턴스를 반환한다.
클라이언트는 이 두 클래스의 존재를 모른다. 클라이언트는 팩토리가 전달하는 객체가 EnumSet
의 하위 클래스이기만 하면 된다. 어느 클래스의 인스턴스인지 알 지 못하고 알 필요도 없다!
이는 JDBC
와 같은 서비스 제공자 프레임워크를 만드는 근간이 된다.
그러나 정적 팩토리 메소드는 장점만 있는 것은 아니다. 단점도 존재한다.
이는 상속보다 컴포지션을 사용하도록 유도하고 불변 타입으로 만들려면 이 제약을 지켜야 한다는 점에서 오히려 장점으로 받아들일 수도 있다.
생성자처럼 API 설명에 명확히 드러나지 않으니 사용자는 정적 팩토리 메소드 방식 클래스를 인스턴스화할 방법을 찾아야한다.
따라서 API 문서를 잘 쓰고 메소드 이름도 널리 알려진 규약을 따라 짓는 식으로 문제를 완화해야 한다.
이와 같이 정적 팩토리 메소드
와 public 생성자
는 각자의 쓰임새가 있으니 상대적인 장단점을 이해하고 사용하는 것이 좋다.
그래도 정적 팩토리
를 사용하는게 유리한 경우가 많으므로 무작정 public 생성자
를 제공하는 습관은 고쳐야 겠다.