참고 블로그
자바(Java)에서 객체를 생성할 때 사용하는 패턴이 여러 가지가 있습니다. 그 중 가장 대표적안 생성자 패턴(constructor pattern)은 지금 채워야 할 필드가 무엇인지 명확히 지정할 수 없습니다. 하지만 빌더 패턴(builder pattern)을 사용하면 어느 필드에 어떤 값을 채워야 할지 명확하게 지정할 수 있습니다.
일반적인 생성자 패턴의 예시는 다음과 같습니다.
package com.example.awsboard.web.dto;
public class Car {
private String id, name;
public Car(String id, String name) {
this.id = id;
this.name = name;
}
// Getter
public String getId() {
return id;
}
public String getName() {
return name;
}
}
String id = "1"; String name = "Charles"; Car car1 = new Car(id, name) Car car2 = new Car(name, car) // ??
일반적인 생성자 패턴은 위와 같이 같은 스트링 타입 변수의 위치가 뒤바뀐 채로 생성되어도 문제점을 찾지 못하고 넘어갈 수도 있다는 점을 알 수 있습니다.
이것을 빌더 패턴으로 바꾸면 다음과 같습니다.
package com.example.awsboard.web.dto;
public class Car {
// final 키워드를 써서 생성자를 통한 입력을 강요함
private final String id, name;
// 클래스 안에 스태틱 형태의 내부 클래스(inner class) 생성
protected static class Builder {
private String id;
private String name;
// id 입력값 받음: 리턴 타입을 Builder 타입으로 한 다음 this를 리턴
public Builder id(String value) {
id = value;
return this;
}
// name 입력값 받음: 리턴 타입을 Builder 타입으로 한 다음 this를 리턴
public Builder name(String value) {
name = value;
return this;
}
// 마지막에 build() 메소드를 실행하면 this가 리턴되도록 함
public Car build() {
return new Car(this);
}
}
// 생성자를 private로 함
// 외부에서는 접근할 수 없고 위의 Builder 클래스에서는 사용 가능
private Car(Builder builder) {
id = builder.id;
name = builder.name;
}
// 빌더 소환: 외부에서 Car.builder() 형태로 접근 가능하게 스태틱 메소드로
public static Builder builder() {
return new Builder();
}
// Getter
public String getId() {
return id;
}
public String getName() {
return name;
}
}
String id = "1";
String name = "Charles";
Car car1 = Car.builder()
.id(id)
.name(name)
.build();
위의 빌더 패턴으로 만든 Car에 대한 단위 테스트는 다음과 같습니다.
package com.example.awsboard.web.dto;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class CarTest {
@Test
public void 빌더_테스트_1() {
String id = "1";
String name = "Charles";
Car car1 = Car.builder()
.id(id)
.name(name)
.build();
assertThat(car1.getId()).isEqualTo(id);
assertThat(car1.getName()).isEqualTo(name);
}
}

롬복(Lombok)으로 빌더 패턴 적용
참고: Spring Boot: Gradle 버전 5 이상에서 롬복 설치 + 단위 테스트
package com.example.awsboard.web.dto;
import lombok.Builder;
import lombok.Getter;
@Getter // Getter 생성
public class LombokCar {
private String id;
private String name;
@Builder // 생성자를 만든 후 그 위에 @Build 어노테이션 적용
public LombokCar(String id, String name) {
this.id = id;
this.name = name;
}
}
단위 테스트는 다음과 같습니다.
package com.example.awsboard.web.dto;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class LombokCarTest {
@Test
public void 빌더_테스트_2() {
String id = "2";
String name = "James";
LombokCar car2 = LombokCar.builder()
.id(id)
.name(name)
.build();
assertThat(car2.getId()).isEqualTo(id);
assertThat(car2.getName()).isEqualTo(name);
}
}






0개의 댓글