아래 내용은 제 깃허브 자바샘플 코드 모음집에서도 확인이 가능합니다.
https://github.com/JooHyukKim/sample_codes_java/tree/main/Effective_Java3E/item1_staticfactorymethod
우리는 종종 객체지향 프로그램의 특징들 중 하나인 오버로딩의 살려 생성자를 구현합니다.
생성자 오버로딩을 구현하는데요. 정말로 오버해서 구현할 때가 많습니다.
"이건 천재적이야" 라고 하면서 저도 그러던 때가 있었습니다.
아래처럼요
생성자 오버로딩은 같은 타입의 매개변수를 가질때 가장 치명적입니다.
예를 들어 아래와 같은 순서를 가진 생성자에서 개발자는 유저네임을 "u1", URL을 "u2"라고 지정했지만
커피한잔하고 와보니 URL이 "u1" 같고 유저네임이 "u2" 같아 보일 수가 있습니다.
에디터에서 보이는 생성자 자체는 순서가 중요하다는 것을 리마인드해주지 않습니다.
new BadHandler(u1, u2, p);
그러면 타입은 맞으니 컴파일은 됩니다, 잊을만하면 큰 문제로 돌아오겠지만요.
그래서 우리는 일반적인 생성자 방법 대신 인스턴스를 반환하는 정적 팩터리 메서드를 고려해야 합니다.
정적 팩터리 메서드는 생성자를 사용하지 않고 정적 static 메서드를 사용해서 클래스 인스턴스를 반환하는 방법입니다.
아래 보시면 팩터리 메서드는 public static으로 시작합니다.
생성자는 private으로 되어있어 접근이 불가능한 상태구요.
정적 팩터리 메서드에 생성자 필요없이 접근이 가능하니
GoodHandler.fromUrlAndPrice(url, price)
이런 식으로 클래스 인스턴스를 생성 & 리턴하면됩니다.
정적 팩터리 메서드 사용하는 것과 안한 것의 차이를 보여드리겠습니다.
본능적으로는 짧은코드인 BadHandler 에 더 호감이 가지만
실제 코드작성시 개발자는 private으로 선언한 생성자에 접근할 수 없습니다.
그래서 GoodHandler.from.... 으로 타이핑을 하게되고 에디터는 친절하게 우리에게 옵션을 알려줍니다. (인텔리제이 아래 예)
이렇게 팩토리메서드는 자칫 치명적일 수 있는 부분을 개발자에게 리마인드 해주는 것이 아닌가 싶습니다.
아이템1 생성자 대신 정적 팩토리 메서드를 고려하라.
클래스의 인스턴스를 얻기위한 일반적인 생성자 방법 대신 인스턴스를 반환하는 정적 팩터리 메서드 기법을 고려해 볼수 있다.
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
장점
1 특성의 묘사를 잘 할 수 있는 이름을 가질 수 있다.
2 호출 할때 마다 인스턴스를 새로 생성하지는 않아도 된다.
3 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
4 입력 매개 변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
5 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
단점
1 상속을 하려면 public 이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
2 정적 팩터리 메서드는 프로그래머가 찾기 어렵다.
보통 팩터리 메서드는 생성자와 달리 API 에 명확히 들어나지 않는다.
흔히 사용하는 정적 팩터리 메서드에 흔히 사용하는 명명 방식들
// from
Date d = Date.from(param);
// of
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
// valueOf
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE)