https://velog.io/@hyeri_hello/Java-3-%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4
builder pattern은 객체 생성을 위해 사용되며,
필수 필드를 생성자에서 설정하고, 선택적 필드를 설정하는 메서드를 통해 설정할 수 있게 해준다.
즉, 객체의 생성 방법과 표현 방법을 분리한다.
빌더 패턴은 생성에서 어떤 문제를 해결하기 위해 고안되었나?
: 객체 생성 시 생성자(Constructor)만 사용할 때 발생할 수 있는 문제를 개선하기 위해 고안됐다.
즉 필수 값에 대해서는 생성자를 통해, 선택 값에 대해서는 메소드를 통해 차례로 값을 입력 받은 후 build() 메소드를 통해 최종적으로 하나의 인스턴스를 return 하는 방식이다.
빌더 패턴은 많은 Optional 한 멤버변수, 파라미터, 지속성 없는 상태 값들에 대해 처리해야 하는 문제들을 해결한다.
예를들어 여행 계획을 세우는 앱을 개발한다고 할때 다음과 같은 요구사항이 있다.
✅ 요구사항1 : 여행 제목, 여행 출발 일, 몇 박, 며칠, 장소, 스케줄
요구사항 1을 만족 하기 위해 아래와 같은 도메인 으로 구성된다.
public class TourPlan{
private String title; // 여행 제목
private LocalDate startDate; // 여행 출발 일
private int nights; // 몇 박
private int days; // 며칠
private String places; // 장소
private List<DetailPlan> plans; // n일차 할 일
}
/**
* n일차 할 일
*/
public class DetailPlan {
private int day; // n일차
private String plan; // 할 일
}
✅ 요구사항2 : 당일 치기 계획도 필요함
요구사항 2 같은경우는 몇박 며칠인지 필요가 없다.
필수적인 정보와 선택적인 정보가 생겼을 땐 어떻게 처리해야 할까?
public interface TourPlanBuilder {
TourPlanBuilder nightsAndDays(int nights, int days);
TourPlanBuilder title(String title);
TourPlanBuilder startDate(LocalDate localDate);
TourPlanBuilder whereToStay(String whereToStay);
TourPlanBuilder addPlan(int day, String plan);
TourPlan getPlan();
}
public class DefaultTourBuilder implements TourPlanBuilder {
private String title;
private int nights;
private int days;
private LocalDate startDate;
private String whereToStay;
private List<DetailPlan> plans;
@Override
public TourPlanBuilder nightsAndDays(int nights, int days) {
this.nights = nights;
this.days = days;
return this;
}
@Override
public TourPlanBuilder title(String title) {
this.title = title;
return this;
}
@Override
public TourPlanBuilder startDate(LocalDate startDate) {
this.startDate = startDate;
return this;
}
@Override
public TourPlanBuilder whereToStay(String whereToStay) {
this.whereToStay = whereToStay;
return this;
}
@Override
public TourPlanBuilder addPlan(int day, String plan) {
if (this.plans == null) {
this.plans = new ArrayList<>();
}
this.plans.add(new DetailPlan(day, plan));
return this;
}
@Override
public TourPlan getPlan() {
return new TourPlan(title, startDate, days, nights, whereToStay, plans);
}
}
return tourPlanBuilder.title("미국 여행")
.nightsAndDays(5, 6)
.startDate(LocalDate.of(2023, 01, 25))
.whereToStay("리조트")
.addPlan(0, "체크인하고 짐 풀기")
.addPlan(0, "저녁 식사")
.getPlan();
public class TourDirector {
private TourPlanBuilder tourPlanBuilder;
public TourDirector(TourPlanBuilder tourPlanBuilder) {
this.tourPlanBuilder = tourPlanBuilder;
}
public TourPlan cancunTrip() {
return tourPlanBuilder.title("칸쿤 여행")
.nightsAndDays(2, 3)
.startDate(LocalDate.of(2020, 12, 9))
.whereToStay("리조트")
.addPlan(0, "체크인하고 짐 풀기")
.addPlan(0, "저녁 식사")
.getPlan();
}
public TourPlan longBeachTrip() {
return tourPlanBuilder.title("롱비치")
.startDate(LocalDate.of(2021, 7, 15))
.getPlan();
}
}
public static void main(String[] args) {
TourDirector director = new TourDirector(new DefaultTourBuilder());
TourPlan tourPlan = director.cancunTrip();
}
빌더 패턴은 굉장히 자주 사용되는 생성 패턴 중 하나로,
실무에서는 Stream.Builder API, StringBuilder, UriComponentsBuilder 등에 활용된다.
reference
https://dev-youngjun.tistory.com/197