-
Item 1. 생성자 대신 정적 팩터리 메서드를 고려하라Book/Effective Java 3E 2022. 10. 2. 10:53반응형
클래스는 생성자와 별도로 정적 팩터리 메서드(static factory method)를 제공할 수 있습니다. 그 클래스의 인스턴스를 반환하는 단순한 정적 메서드입니다.
// 생성자 private final boolean value; public Boolean(boolean value) { this.value = value; } // 정적 팩터리 메서드 public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
장점
- 이름을 가질 수 있습니다. 정적 팩터리는 이름만 잘 지으면 반환될 객체의 특성을 쉽게 묘사할 수 있습니다. 예컨대 생성자인 BigInteger(int, int, Random)과 정적 팩터리 메서드인 BigInteger.probablePrime 중 어느 쪽이 '값이 소수인 BigInteger를 반환한다'는 의미를 더 잘 설명할 것 같은지 생각해 보면 됩니다.
- 호출될 때마다 인스턴스를 새로 생성하지 않아도 됩니다. 불변 클래스(immutable class)는 인스턴스를 미리 만들어 놓거나 새로 생성한 인스턴스를 캐싱하여 재활용하는 식으로 불필요한 객체 생성을 피할 수 있습니다. 대표적인 예로 Boolean.valueOf(boolean) 메서드는 객체를 아예 생성하지 않습니다.
- 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있습니다. 클래스에서 만들어 줄 객체의 클래스를 선택하는 유연함이 있습니다. 리턴 타입은 인터페이스로 지정하고, 그 인터페이스의 구현체는 API로 노출시키지 않지만 그 구현체의 인스턴스를 만들어 줄 수 있다는 말입니다. java.util.Collections가 그 예에 해당합니다.
- 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있습니다. 반환 타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관이 없습니다. EnumSet 클래스는 생성자 없이 오직 정적 팩터리만 제공하는데, 원소가 64개 이하면 원소들을 long 변수 하나로 관리하는 RegularEnumSet의 인스턴스를, 65개 이상이면 long 배열로 관리하는 JumboEnumSet의 인스턴스를 반환합니다.
- 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 됩니다. 이런 유연함은 서비스 제공자 프레임워크(service provider framework)를 만드는 근간이 됩니다. 대표적인 서비스 제공자 프레임워크로는 JDBC(Java Database Connectivity)가 있습니다.
단점
- 상속을 하려면 public이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없습니다. 앞서 이야기한 컬렉션 프레임워크의 유틸리티 구현 클래스들을 상속할 수 없다는 이야기 입니다.
- 정적 팩터리 메서드는 프로그래머가 찾기 어렵습니다. 생성자처럼 API 설명에 명확히 드러나지 않으니 사용자는 정적 팩터리 메서드 방식 클래스를 인스턴스화할 방법을 알아내야 합니다.
정적 팩터리 메서드와 public 생성자는 각자의 쓰임새가 있으니 상대적인 장단점을 이해하고 사용하는 것이 좋다.
그렇다고 하더라도 정적 팩터리를 사용하는 게 유리한 경우가 더 많으므로 무작정 public 생성자를 제공하던 습관이 있다면 고치자.
[참고 정보]
이펙티브 자바 Effective Java 3/E 도서 [조슈아 블로크 저]
반응형'Book > Effective Java 3E' 카테고리의 다른 글
Item 6. 불필요한 객체 생성을 피하라 (0) 2022.10.10 Item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) 2022.10.10 Item 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) 2022.10.07 Item 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) 2022.10.07 Item 2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) 2022.10.03