정적 팩터리 메소드란 인스턴스를 생성, 반환하는 static method이다.
// private 생성자이므로 외부에서 생성자 호출 불가
private ExampleClass(){};
// 정적 팩터리 메소드를 통하여 instance 생성
static ExampleClass newInstance(){
return new ExampleClass();
}
위와 같이 생성자를 숨기고 오로지 static method로만 인스턴스를 만들 수 있도록 하는 것이다.
생성자와 인자들만으로 반환될 객체의 특징을 설명하는 것은 부족하다. 정적 팩터리 메소드를 통하여 반환될 객체의 특성을 잘 묘사할 수 있다.
불변 클래스 ( item 17 ) 는 인스턴스를 미리 만들어 놓거나, 생성된 인스턴스를 캐싱하여 재활용하면 불필요한 객체 생성을 줄일 수 있다. 비슷한 기법으로 flyweight pattern(경량 패턴)이 있다.
Flyweight Pattern - 한개의 고유 상태를 다른 객체들에서 공유하게 만들어 메모리 사용량을 줄인다. 식빵맘
반환할 객체를 자유롭게 선택할 수 있는 것이다. 반환타입으로 인터페이스를 사용하여 구현 클래스를 공개하지 않고도 객체를 반환할 수 있다. 인터페이스 기반 프레임워크를 만드는 핵심 기술이다.
위 항목에서 연속된 장점으로, 한 정적 메소드에서 매개변수 상황에 맞게 최적의 클래스를 선택하여 반환할 수 있는 것이다. 예를 들어 EnumSet 클래스는 원소가 64개 이하면 RegularEnumSet 인스턴스를 사용하고, 원소가 65개 이상이면 JumboEnumSet 인스턴스를 사용한다.
연속해서 인터페이스를 이용하여 작성할 수 있기 때문에, 당장 실제 반환해야하는 구현체가 없어도 메소드 작성에는 문제가 없다.
JDBC를 예를 들었는데, JDBC 프레임워크 구현에 구현체는 필요하지 않다는 것이다. 언제든지 실제 구현체를 넣어주기만 하면 되기 때문이다.
책에서 서비스 제공자 프레임워크의 구성요소에 대한 이야기가 있다. 서비스 제공자 프레임워크의 핵심 구성요소 세 가지가 있다는 것이다.
- 구현체 만드는 사람들이 무엇을 구현하고 (서비스 인터페이스),
- 구현체를 어떻게 프레임워크에 등록하는지 알아야하고 (제공자 등록 API),
- 클라이언트는 어떻게 프레임워크를 사용하면 되는지 알아야한다 (서비스 접근 API).
- 추가적으로 서비스 인터페이스의 인스턴스를 생성하는 팩터리를 제공하기도 하는데, 이게 없으면 리플렉션 ( item 65 ) 으로 클래스 찾아서 인스턴스화 시켜야된다 (서비스 제공자 인터페이스).
상속을 못한다는 것은 그냥 봤을 때는 단점이지만 상속보다는 컴포지션을 쓰고, 불변 타입으로 만들려면 ( item 18, item 17 ) 오히려 장점일 수 있다.
API 문서를 잘 써놓던가, 정적 팩터리 메소드 명명 방식의 국룰로 승부보자는 것이 책의 메시지이다.
정적 팩터리 메소드와 public 생성자는 각자의 쓰임새가 있으니 장단점을 잘 파악하고 적절하게 사용하자. 정적 팩터리 메소드가 유리한 경우가 많으니 무작정 public 생성자 쓰던 습관이 있다면 고치자.
반환하는 인스턴스를 메소드에서 언제 어느 인스턴스가 살아있게 할지 통제할 수 있다. 응용하여 singleton ( item 3 ) 이나 noninstantiable ( item 4 ) 을 만들 수 있다. 불변 값 클래스에서 동치인 인스턴스가 하나뿐임을 보장하도록 할 수도 있다.