• 동일한 절차를 거쳐 다양한 구성의 인스턴스를 만드는 방법
  • 복잡한 객체를 생성하는 클래스와 표현하는 클래스를 분리하여 동일한 절차에서도 다양한 구성의 인스턴스를 만들 수 있다

구현

  • 도메인
public class TourPlan {

    private String title;
    private int nights;
    private int days;
    private LocalDate startDate;
    private String whereToStay;
    private List<DetailPlan> plans;

    public TourPlan() {}

    public TourPlan(String title, int nights, int days, LocalDate startDate, String whereToStay, List<DetailPlan> plans) {
        this.title = title;
        this.nights = nights;
        this.days = days;
        this.startDate = startDate;
        this.whereToStay = whereToStay;
        this.plans = plans;
    }
}
  • 빌더 인터페이스
public interface TourPlanBuilder {

    TourPlanBuilder title(String title);

    TourPlanBuilder nightsAndDays(int nights, int days);

    TourPlanBuilder startDate(LocalDate localDate);

    TourPlanBuilder whereToStay(String whereToStay);

    TourPlanBuilder addPlan(int day, String plan);

    TourPlan getPlan();
}
  • 빌더 구현체
    • return 타입으로 builder를 사용해 체이닝이 가능해진다
    • 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 title(String title) {
        this.title = title;
        return this;
    }

    @Override
    public TourPlanBuilder nightsAndDays(int nights, int days) {
        this.nights = nights;
        this.days = days;
        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, nights, days, startDate, whereToStay, plans);
    }
}
public class Main {

    public static void main(String[] args) {
        TourPlanBuilder builder = new DefaultTourBuilder();
        TourPlan plan = builder.title("칸쿤 여행")
                .nightsAndDays(2, 3)
                .startDate(LocaldDate.of(2022, 01, 1))
                .whereToStay("리조트")
                .addPlan(0, "저녁 식사")
                .getPlan();
    }
}

장점

  1. 필요한 필드만 가지고 인스턴스를 생성할 수 있다
  2. 가독성이 좋아진다
  3. 유연성이 높아진다
    • 새로운 필드가 추가될 때마다 생성자를 만들 필요가 없어 변경을 최소화할 수 있다

단점

  1. 객체를 생성하기 위해 항상 builder를 먼저 만들어야 한다
  2. 구조가 복잡해진다