정적 팩터리 + 생성자의 제약 = 선택적 매개변수가 많을 때 적절히 대응하기 어렵다
1. 대안A) 점층적 생성자 패턴 (telescoping constructor pattern)
필수 매개변수 + 선택 매개변수
원하는 매개변수를 모두 포함한 생성자 중 가장 짧은 것을 골라 호출한다
권장하지 않는다. 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵다.
2. 대안B) 자바빈즈 패턴 (JavaBeans pattern)
자바빈즈 패턴의 단점
- 객체 하나를 만들려면 메서드를 여러개 호출해야 한다. (객체 1개 : 메서드 호출 N개)
- 객체가 완전히 생성되기 전까지는 일관성(consistency)이 무너진 상태에 놓인다. -> 런타임문제 디버깅 하드해진다.
- 클래스를 불변으로 만들 수 없다. -> thread 안전하지 않다.
단점 해소를 위한 freezing 방법이 있지만, freeze 메서드를 확실히 호출했는지 컴파일러가 보증할 방법이 없어서 런타임에 취약하다.
3. 대안 C) 빌더 패턴 (Builder pattern)
- 필수 매개변수만으로 생성자(정적 팩터리)를 호출해 빌더 객체를 얻는다.
- 일종의 세터메서드로 원하는 선택 매개변수를 설정한다.
- build 메서드를 호출해 필요한 객체를 얻는다 (주로 불변)
빌더 패턴의 메서드 호출 연결 : 풀루언트 API(fluent API) or 메서드 연쇄(method chaining)
주의 : build() 메서드에서 호출하는 생성자에서 여러 매개변수의 불변식(invariant)을 검사하자
불변식 : 프로그램이 실행되는 동안, 정해진 기간동안 반드시 만족해야하는 조건 (불변[immutable]은 불변식의 극단적인 예)
4. 빌더패턴의 쓰임새
계층적으로 설계된 클래스와 함께 사용하기 좋다.
시뮬레이트한 셀프 타입 (simulated self-type) : 추상메서드 self를 더해 하위클래스에서 형변환 없이 메서드 연쇄를 지원한다. [Pizza.Builder 클래스는 재귀적 타입 한정을 이용하는 제네릭 타입이다.]
재귀적 타입 한정 : 자기 자신이 들어간 표현식을 사용해 타입 매개변수의 허용범위를 한정한다.
공변 반환 타이핑 (covariant return typing) : 하위 클래스의 메서드가 상위 클래스의 메서드가 정의한 반환 타입이 아닌, 하위 타입을 반환하는 기능
NyPizza.Builder는 NyPizza 반환, Calzone.Builder는 Calzone 반환
빌더를 이용하면 가변인수(varargs) 매개변수를 여러개 사용할 수 있다.
addTopping 메서드
5. 빌더 패턴의 단점
객체를 만들때 빌더부터 마들어야하는데, 빌더 생성비용이 크지는 않지만, 성능에 민감한 상황에서는 문제이다.
매개변수가 4개이상은 되어야 값어치를 한다.
'Dev Book Review > Effective Java' 카테고리의 다른 글
[Effective Java] item6. 불필요한 객체 생성을 피하라 (0) | 2020.04.15 |
---|---|
[Effective Java] item5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2020.04.15 |
[Effective Java] item4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2020.04.15 |
[Effective Java] item3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2020.04.15 |
[Effective Java] item1. 생성자 대신 정적 팩터리 메서드를 고려하라 (0) | 2020.04.15 |