티스토리 뷰
정적팩토리나 생성자에는 똑같은 제약이 있다.
→ 둘 다 선택적 매개변수가 많을때 적절히 대응이 어렵다는 점
이렇게 선택적 매개변수가 많을때는 어떻게 효율적으로 사용할 수 있을까 ?
- 점층적 생성자 패턴
- 자바빈즈 패턴
- 빌더 패턴
점층적 생성자 패턴 (telescoping constructor pattern)
필수 매개변수만 받는 생성자 → 필수 매개변수, 선택 매개변수1 ... 필수 매개변수, 선택 매개변수 n ... 이렇게 전부 다 받는 생성자까지 늘려가는 방식
→ 쓸 수는 있지만, 매개변수 개수가 많아지면 클라이언트 코드 작성이나 읽기가 어렵다.
→ 각 값의 의미가 헷갈림.
→ 타입이 같은 매개변수가 연달아 있으면 찾기 어려움.
→ 결국 런타임에 엉뚱한 동작 발생.
자바빈즈 패턴 (JavaBeans pattern)
매개변수가 없는 생성자로 객체를 만든 후, setter 메서드를 호출해 원하는 매개변수의 값을 설정하는 방식
→ 코드가 길어지지만 인스턴스 생성이 쉬움.
→ 코드 가독성이 좋음.
→ 객체 하나를 만들기 위해선 setter 메소드 호출이 너무 잦을 수 있음.
→ 객체가 완전히 생성되기 까지는 일관성 (consistency)가 무너진 상태임.
→ 클래스를 불변으로 만들수 없음.
→ 스레드 안전성을 위해서는 추가작업이 필요함.
빌더 패턴 (Builder pattern)
점층적 생성자 패턴의 안전성 + 자바빈즈 패턴의 가독성 ⇒ 빌더 패턴
클라이언트는 필요한 객체를 직접 만드는 대신, 필수 매개변수만으로 생성자(혹은 정적 팩토리)를 호출해 빌더 객체를 얻는다.
→ 쓰기 쉽고, 읽기 쉬움.
→ 유연하다. (빌더 하나로 여러 객체를 순회하면서 만들 수 있고, 빌더에 넘기는 매개변수에 따라 다른 객체를 만들 수 도 있다.)
→ 코드가 장황해 매개변수가 4개 이상은 되어야 값어치를 한다. (API 는 시간이 지날수록 매개변수가 많아지는 경향이 있다.)
→ 객체를 만들기 이전에 빌더 부터 만들어야 한다. (빌더 생성 비용이 크지는 않지만 성능에 민감한 상황에서는 문제가 될 수 있음.)
→ 생성자나 정적팩토리 방식으로 시작했다가 추후에 매개변수가 많아지면 빌더 패턴으로 바꿀수도 있지만, 애초에 빌더로 시작하는 편이 권장된다.
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// 필수 매개변수
private final int servingSize;
private final int servings;
// 선택 매개변수 - 기본값으로 초기화한다.
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
public NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
// 클라이언트 코드
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
.calories(100)
.sodium(35)
.carbohydrate(27)
.build();
'책 > 이펙티브자바' 카테고리의 다른 글
아이템4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2021.06.20 |
---|---|
아이템3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2021.06.20 |
아이템1. 생성자 대신 정적 팩토리 메소드를 고려하라 (0) | 2021.06.20 |
어떻게 읽을지 ... (0) | 2021.06.20 |
이펙티브자바 책 샀다. (0) | 2021.06.18 |
- Total
- Today
- Yesterday
- 이펙티브자바
- 백기선 스터디
- HTTP 완벽가이드
- dreamcoding
- java
- GCP
- 프로그래머스 SQL
- JPA 연관관계 매핑
- js api
- 킹수빈닷컴
- JS 딥다이브
- js array
- 이펙티브자바 아이템59
- Spring Security
- 김영한 JPA
- REST API
- 모던자바스크립트
- HTTP 완벽 가이드
- 프로그래머스
- BOJ
- js promise
- 드림코딩
- 백준
- 패스트캠퍼스 컴퓨터공학 완주반
- ㅇㄷㅇㅈ
- 이펙티브자바 아이템60
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초
- http
- 김영한 http
- 이펙티브자바 스터디
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |