Builder 패턴
2022. 3. 30. 12:05ㆍBackEnd(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);
자바 빈 패턴의 장점
- 각 인자의 의미를 파악하기 쉬워짐
- 복잡하게 여러 개의 생성자를 만들지 않아도 된다.
단점
- 객체를 한 번에 생성하지 않고 반복된 호출로 객체를 생성하려 한다.
- 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 빌더 패턴 장점
- 각 인자의 의미를 파악하기 쉬워짐
- setter 메서드가 없으므로 변경 불가능(Immutable) 객체를 만들 수 있다.
- 한번에 객체를 생성하므로 객체 일관성이 깨지지 않는다.
- 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 |