Builder 패턴

2022. 3. 30. 12:05BackEnd(Java)/Design Pattern

엔티티를 구성 중 Setter를 사용하지 않고 엔티티 변경을 해 줘야 한다는 것은 인지하고 그러면 어떤 방식으로 엔티티의 각 변수에 값을 설정해 줄 수 있는지 구글에서 찾아보게 되었다.

찾아보던 중 Builder Pattern 키워드를 알게 되었고 잘 정리해놓은 글을 찾게 되어 해당 블로그를 참고하여 요약 및 정리를 할 것이다.

 

빌더 패턴(Builder Pattern) 

(객체의 생성 방법과 표현 방법을 분리한다)

빌더 패턴은 객체를 생성할 때 흔하게 사용하는 패턴이다. 나는 이펙티브 자바의 빌더 패턴과 Lombok의 @Builder에 대해서 정리할 것이다.

 

Effective Java의 빌더 패턴

이펙티브 자바의 빌더 패턴은 가독성/유지보수가 더 편해지므로 빌더 패턴을 쓰라고 권장한다.

생성자 인자가 많을 때 Builder 패턴 적용을 고려해라.

보통 setter를 사용하여 값을 설정하는 방식을 자바 빈 패턴이라고 한다.

NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohdydrate(27);
 

자바 빈 패턴의 장점

  1. 각 인자의 의미를 파악하기 쉬워짐
  2. 복잡하게 여러 개의 생성자를 만들지 않아도 된다.

 

단점

  1. 객체를 한 번에 생성하지 않고 반복된 호출로 객체를 생성하려 한다.
  2. setter 메서드가 있으므로 불변(변경 불가능, immutable)의 클래스를 만들 수가 없다.

 

 

Effective Java의 빌더 패턴 예시

// 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;
    }
}
 
 

객체 생성 방법

// 각 줄마다 builder를 타이핑하지 않아도 되어 편리하다.
NutritionFacts cocaCola = new NutritionFacts
    .Builder(240, 8)    // 필수값 입력
    .calories(100)
    .sodium(35)
    .carbohydrate(27)
    .build();           // build() 가 객체를 생성해 돌려준다.
 

 

EffectiveJava 빌더 패턴 장점

  1. 각 인자의 의미를 파악하기 쉬워짐
  2. setter 메서드가 없으므로 변경 불가능(Immutable) 객체를 만들 수 있다.
  3. 한번에 객체를 생성하므로 객체 일관성이 깨지지 않는다.
  4. build() 함수가 유효성 검사를 할 수 있음.

 


 

Lombok @Builder

- 예시 1

@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;
}
 

 

- 예시 2

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;

    @Builder
    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
        this.servingSize = servingSize;
        this.servings = servings;
        // ...
    }
}
 

객체 생성 방법

NutritionFacts facts = NutritionFacts.builder()
    .calories(230)
    .fat(10)
    .build();
 

 

단, 주의할 점은 클래스 선언부에 @Builder를 사용하면 안 된다(예시 1처럼 하면 안 됨)

@Builder를 클래스에 달아주면 @AllArgsConstructor를 달아주는 것과 같기 때문에 바람직하지 않음

 

@NoArgsConstructor
파라미터가 없는 기본 생성자를 생성
@AllArgsConstructor
모든 필드 값을 파라미터로 받는 생성자를 만듦
@RequiredArgsConstructor
final이나 @NonNull인 필드 값만 파라미터로 받는 생성자 만듦

 


 

 

 

 

반응형

'BackEnd(Java) > Design Pattern' 카테고리의 다른 글

커맨드 패턴  (1) 2024.10.07
데코레이터 패턴  (0) 2024.09.24
옵저버 패턴  (0) 2024.09.23
전략 패턴  (2) 2022.10.10
디자인 패턴을 왜 써야할까?  (0) 2022.10.10