자바에서 객체를 생성할 때 일반적으로 생성자를 이용한다. 그런데, 가만히 보면 프로그래머가 생성자의 순서를 외워서 인스턴스를 만들어야 한다. 그런데.. 몇 가지 문제점이 있다.
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 |