JaPark Bug World
item2. 생성자에 매개변수가 많다면 빌더를 고려하라. 본문
* 해당 내용은 인프런 이펙티브 자바 완벽 공략 1부 백기선님의 영상을 기준으로 작성하였습니다. https://inf.run/fnnRy
생성자에 매개변수가 많다면 빌더를 고려하라.
- 정적 팩터리와 생성자에 선택적 매개변수가 많을 때 고려할 수 있는 방안
- 대안1: 점층적 생성자 패턴 또는 생성자 체이닝
- 매개변수가 늘어나면 클라이언트 코드 작성하거나 읽기 어렵다.
- 대안1: 점층적 생성자 패턴 또는 생성자 체이닝
- 점층적 생성자
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 NutritionFacts(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
calories = 0;
fat = 0;
sodium = 0;
carbohydrate = 0;
}
public NutritionFacts(int servingSize, int servings, int calories) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
fat = 0;
sodium = 0;
carbohydrate = 0;
}
public NutritionFacts(int servingSize, int servings, int calories, int fat) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
sodium = 0;
carbohydrate = 0;
}
public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
carbohydrate = 0;
}
public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
}
}
- 생성자 체이닝
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 NutritionFacts(int servingSize, int servings) {
this(servingSize, servings, 0);
}
public NutritionFacts(int servingSize, int servings, int calories) {
this(servingSize, servings, calories, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat) {
this(servingSize, servings, calories, fat, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
this(servingSize, servings, calories, fat, sodium, 0);
}
public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = 0;
}
}
- 단점
public static void main(String[] args) {
// 인스턴스를 만들 때 어떤 파라미터를 줘야 하는지 파악하기가 어렵다.
NutritionFacts cola = new NutritionFacts()
}
- 대안2: 자바빈즈 패턴
- 완전한 객체를 만들려면 메서드를 여러번 호출해야 한다. (일관성이 무너진 상태가 될 수도 있다.)
- 클래스를 불변으로 만들 수 없다.
public class NutritionFacts {
private int servingSize; // 필수
private int servings; // 필수
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
public NutritionFacts() {}
public void setServingSize(int servingSize) {
this.servingSize = servingSize;
}
public void setServings(int servings) {
this.servings = servings;
}
public void setCalories(int calories) {
this.calories = calories;
}
public void setFat(int fat) {
this.fat = fat;
}
public void setSodium(int sodium) {
this.sodium = sodium;
}
public void setCarbohydrate(int carbohydrate) {
this.carbohydrate = carbohydrate;
}
}
public static void main(String[] args) {
NutritionFacts cola = new NutritionFacts();
cola.setServingSize(10);
cola.setServings(10);
cola.setCalories(10);
cola.setFat(10);
cola.setSodium(10);
cola.setCarbohydrate(10);
}
- 단점
public static void main(String[] args) {
// 필수값으로 생성이 안된 부분에 대한 안정성을 보장할 수 없다.
NutritionFacts cola = new NutritionFacts();
cola.setCalories(10);
cola.setFat(10);
cola.setSodium(10);
cola.setCarbohydrate(10);
}
- Builder pattern
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;
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.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 static void main(String[] args) {
NutritionFacts cola = new Builder(100, 10)
.calories(100)
.sodium(100)
.carbohydrate(100)
.build();
}
public static void main(String[] args) {
// 필수값만 입력받아 빌더 생성 가능
// 최종적으로 .build()가 호출되야 함.
NutritionFacts cola = new Builder(100, 100).build();
}
- 롬복을 이용하여 코드의 양을 줄일 수 있다.
import lombok.Builder;
@Builder
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 void main(String[] args) {
NutritionFacts nutritionFacts = new NutritionFactsBuilder()
.servingSize(100)
.servings(100)
.build();
}
}
'개발새발 > Effective Java' 카테고리의 다른 글
item3. private 생성자나 열거 타입으로 싱글턴임을 보증하라. (0) | 2024.03.28 |
---|---|
item3. private 생성자나 열거 타입으로 싱글턴임을 보증하라. (0) | 2024.03.28 |
item2. 생성자에 매개변수가 많다면 빌더를 고려하라. (0) | 2024.03.28 |
item2. 생성자에 매개변수가 많다면 빌더를 고려하라. (0) | 2024.03.26 |
Item1. 생성자 대신 정적 팩터리 메서드를 고려하라. (0) | 2024.03.26 |