자바에서 객체를 생성할 때 일반적으로 생성자를 이용한다. 그런데, 가만히 보면 프로그래머가 생성자의 순서를 외워서 인스턴스를 만들어야 한다. 그런데.. 몇 가지 문제점이 있다.
1. 타입이 같은 파라미터를 헷갈릴 수 있다.
public Order(int id, int UUid, String orderDetail, String Order) //id, UUid .. 그 다음이 뭐였더라?
{
....
}
Order 객체를 생성하기 위해 생성자에서 값을 넣는 도중 순서가 생각이 안난다면, 클래스를 직접 보거나 IDE에서 마우스를 갖다 대야 볼 수 있다.
2. 생성자의 파라미터가 많으면 다 넣어줘야 한다.
public Order(int id, int UUID, String name, String OrderDetail ....) //파라미터가 10개, 20개라면!?
{
....
}
파라미터가 많으면, 외우기도 힘들고 쓰기도 귀찮다.
생성자에 값을 명시적으로 넣을 수는 없을까?
위와 같은 질문에 착안하여 만들어진게 빌더 패턴이다.
빌더 (Builder) 직역 그대로 무언가를 만드는 역할이다.
// Effective Java의 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;
public static class Builder {
// Required parameters(필수 인자)
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values(선택적 인자는 기본값으로 초기화)
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 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 carbohydrate(int val) {
carbohydrate = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private 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(); // build() 가 객체를 생성해 돌려준다.
객체에 어떤 값이 들어가는지 눈에 확 보인다. 또한 setter 메서드를 만들지 않을 수 있기 때문에 객체를 한 번 만들고 값이 변경되지 않아야 되는 상황 (e.g. 엔티티 클래스)에적합하다.
그런데, 롬복에서 이러한 빌더 패턴을 지원해주는 @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;
}
호출하는 방법도 달라지지 않는다. 타이핑을 획기적으로 줄일 수 있는 롬복을 사용하길 적극 추천한다.
'Java' 카테고리의 다른 글
Java의 static method는 왜 오버라이딩 되지 않는가 (0) | 2022.01.23 |
---|---|
오늘의 질문 : Java의 Enum은 왜 생성자가 있는가? (0) | 2021.08.17 |
자바 어노테이션 (0) | 2021.07.08 |
모던 자바인액션 1장 (0) | 2021.06.26 |
Java Collection (0) | 2021.04.01 |