정적 팩토리 메서드를 고려하라
public class Boolean {
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
private final boolean value;
private Boolean(boolean value) {
this.value = value;
}
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
}
정팩 팩토리 메서드가 생성자보다 좋은 이유 다섯가지
- 이름을 가질 수 있다.
- 이름을 잘 지으면 객체의 특성을 쉽게 묘사할 수 있다.
- 한 클래스에 시그니처가 여러개인 생성자가 존재할 경우 정적 패토리 메서드를 사용해 각각의 차이를 잘 드러내는 이름을 짓자.
- Private 접근제어를 가진 내부 생성자를 이용하기 때문에
- 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.
- 인스턴스의 생명주기를 클래스내에서 제어 가능하다 -> 이를 인스턴스 통제라함
- 객체를 싱글톤으로 만들수도, 인스턴화가 불가능한 객체로 만들 수 도있다.
- 캐싱이 가능하다
- 외부 생성자가 아닌 Private접근자인 내부 생성자를 이용해 생성하기 때문에
- 때문에 생성 비용이 큰 객체를 자주 요청하는 상황일 경우 용이하다.
- 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.
- 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
- 정적 팩토리 메서드의 반환타입을 추상클래스 혹은 인터페이스로 설정한 뒤 그 하위 클래스인 구현체를 반환가능하다.
- 반환 타입을 추상화함으로서 객체는 유연성을 가진다.
- 클래스 내부 로직을 숨길 수 있어 캡슐화의 이점 또한 존재한다.
- 가장 큰 장점은 아무래도 "추상화" 해당 객체를 사용할때 코드 작성자는 해당 객체의 내부 로직과 반환 타입에 대해 정확히 파악하지 않아도 객체의 역할과 책임을 쉽게 이해하고 사용 가능하다.
- 입력 매개변수에 따라 배번 다르클래스의 객체르 반환할 수 있다.
- 3번의 장점과 비슷한 이유
- 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
- 정적 팩토리 메서드는 추상화된 타입을 반환하기에 작성당시에 구현체가 존재하지 않아도된다. 구현체는 나중에 개발되거나 런타임 환경에서 동적으로 구현되어도 괜찮다는 뜻 이것도 3번째 장점과 비슷한듯
단점에대해서도 알아보자
- 상속을 하려면 publicdlsk protected 생성자가 필요하다.
- 하지만 이러한 단점은 상속보단 컴포지션을 사용하라는 점을 지켜야되는 제약으로 오히려 장점이 될 수 도...
- 정적 팩토리 메서드는 프로그래머가 찾기 어렵다.
- API 설명란에 생성자처럼 명확하게 드러나지않아 정적 팩토리 메서드로 인스턴스화된 객체의 내부 로직 파악이 힘들 수 있다.
- from:
- 하나의 매개변수를 받아 해당 타입의 인스턴스를 반환하는 형변환 메서드
- 예: Date.from(instant)
- of:
- 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드
- 예: EnumSet.of(JACK, QUEEN, KING)
- valueOf:
- from과 of의 더 자세한 버전
- 예: BigInteger.valueOf(Integer.MAX_VALUE)
- instance 혹은 getInstance:
- (매개변수를 받는다면) 매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지는 않음
- 예: StackWalker.getInstance(options)
- create 혹은 newInstance:
- instance 혹은 getInstance와 같지만, 매번 새로운 인스턴스를 생성해 반환함을 보장
- 예: Array.newInstance(classObject, arrayLen)
- getType:
- getInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩토리 메서드를 정의할 때 사용
- 예: Files.getFileStore(path)
- newType:
- newInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩토리 메서드를 정의할 때 사용
- 예: Files.newBufferedReader(path)
- type:
- getType과 newType의 간결한 버전
- 예: Collections.list(legacyLitany)
핵심 정리 -> 정적 팩토리 메서드와 public 생성자 각각의 쓰임새가 존재한다. 다만 정적 팩토리 메서드를 이용하는 경우가 더 이로운 상황이 많기때문에 정적 팩토리 메서드로 코드를 먼저 작성해보는 습관을 가져보자.
생성자에 매개변수가 많다면 빌더를 고려하라
정적 팩토리 메서드와 public 생성자에겐 같은 단점이 존재한다.
->선택적 매개변수가 많을 경우 적절한 대응이 어렵다.
매개변수가 많아질 경우 코드를 작성하거나 읽기도 어려워진다.
또한 매개변수의 순서가 잘못될 경우 컴파일 과정에서는 문제가 발생하지 않아도 런타임 상황에서 예외가 발생 할 수 있다.
빌더패턴 : 점층적 생성자 패턴과 자바빈즈 패턴의 장점을 취한 디자인 패턴
선택적 매개변수를 먼저 초기화 후
내부 스태틱 클래스인 빌더 클래스에서 매개변수를 받고 초기화 한다.
'책 > EffectiveJava' 카테고리의 다른 글
10장 예외 (0) | 2024.09.05 |
---|---|
4장 클래스와 인터페이스 (1) | 2024.08.31 |