/**
* 여행 계획
*/
public class TourPlan {
private String title; // 여행 제목
private String place; // 여행 장소
private LocalDate startDate; // 출발일
private int nights; // n박
private int days; // m일
private List<DailyPlan> plans; // m일차 하루 계획
}
/**
* n일차 하루 계획
*/
public class DailyPlan {
private int day; // n일차
private String place; // 갈 곳
private String doing; // 할 일
}
/**
* 기본 생성자 (필수)
*/
public TourPlan() {
}
/**
* 일반적인 여행 계획 생성자
*
* @param title 여행 제목
* @param startDate 출발 일
* @param nights n박
* @param days m일
* @param whereToStay 머물 장소
* @param plans n일차 할 일
*/
public TourPlan(String title, String place, LocalDate startDate, int nights, int days,
List<DailyPlan> plans) {
this.title = title;
this.place = place;
this.nights = nights;
this.days = days;
this.startDate = startDate;
this.plans = plans;
}
/**
* 당일치기 여행 계획 생성자
*
* @param title 여행 제목
* @param startDate 출발 일
* @param plans 1일차 할 일
*/
public TourPlan(String title, String place, LocalDate startDate, List<DailyPlan> plans) {
this.title = title;
this.place = place;
this.startDate = startDate;
this.plans = plans;
}
// 순서를 파악이 어렵고, 가독성이 떨어진다.
new TourPlan("여봉봉과 함께하는 1주년 여행", "부산", LocalDate.of(2021,12, 24), 3, 4,
Collections.singletonList(new DailyPlan(1, "자갈치 시장", "회떠오기")));
// 생성자를 만들지 않고 당일치기 객체를 생성하면 불필요한 Null을 채워야한다.
new TourPlan("전주 맛집 투어", "전주", LocalDate.of(2021,12, 24), null, null, null,
Collections.singletonList(new DetailPlan(1, "한옥마을", "한복 입기")));
TourPlan tourPlan = new TourPlan();
tourPlan.setTitle("칸쿤 여행");
tourPlan.setNights(2);
tourPlan.setDays(3);
tourPlan.setStartDate(LocalDate.of(2021, 12, 24));
tourPlan.setPlace("칸쿤");
tourPlan.addPlan(1, "어쩌고 호텔", "체크인 이후 짐풀기");
tourPlan.addPlan(1, "어쩌고 호텔","저녁 식사");
tourPlan.addPlan(2, "어쩌고 호텔", "조식 먹기");
tourPlan.addPlan(2, "저쩌고 비치", "해변가 산책");
tourPlan.addPlan(2, "이러쿵 음식점", "점심은 수영장 근처 음식점에서 먹기");
...
tourPlan.addPlan(3, "어쩌고 호텔", "체크아웃");
public interface TourPlanBuilder {
TourPlanBuilder nightsAndDays(int nights, int days);
TourPlanBuilder title(String title);
TourPlanBuilder startDate(LocalDate localDate);
TourPlanBuilder place(String place);
TourPlanBuilder addPlan(int day, String place, String doing);
TourPlan getPlan();
}
public class DefaultTourBuilder implements TourPlanBuilder {
private String title;
private int nights;
private int days;
private LocalDate startDate;
private String place;
private List<DeilyPlan> 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 place) {
this.place = place;
return this;
}
@Override
public TourPlanBuilder addPlan(int day, String place, String doing) {
if (this.plans == null) {
this.plans = new ArrayList<>();
}
this.plans.add(new DailyPlan(day, place, doing));
return this;
}
@Override
public TourPlan getPlan() {
return new TourPlan(title, startDate, days, nights, place, plans);
}
}
return tourPlanBuilder.title("칸쿤 여행")
.nightsAndDays(2, 3)
.startDate(LocalDate.of(2020, 12, 9))
.place("칸쿤")
.addPlan(1, "어쩌고 호텔", "체크인하고 짐 풀기")
.addPlan(1, "어쩌고 호텔", "저녁 식사")
.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))
.place("칸쿤")
.addPlan(1, "어쩌고 호텔", "체크인하고 짐 풀기")
.addPlan(1, "어쩌고 호텔", "저녁 식사")
.getPlan();
}
public TourPlan busanTrip() {
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();
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder(builderMethodName = "**travelCheckListBuilder**")
@ToString
public class TravelCheckList {
private Long id;
private String passport;
private String flightTicket;
private String creditCard;
private String internationalDriverLicense;
private String travelerInsurance;
public static TravelCheckListBuilder **builder**(Long id) {
if(id == null) {
throw new IllegalArgumentException("필수 파라미터 누락");
}
return **travelCheckListBuilder**().id(id);
}
}
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
앞서 설명한 Builder 패턴을 자동으로 생성해주는데, builderMethodName에 들어간 이름으로 빌더 메서드를 생성해준다.
public class MainClass {
public static void main(String[] args) {
// 빌더패턴을 통해 어떤 필드에 어떤 값을 넣어주는지 명확히 눈으로 확인할 수 있다!
TravelCheckList travelCheckList = TravelCheckList.builder(145L)
.passport("M12345")
.flightTicket("Paris flight ticket")
.creditCard("Shinhan card")
.internationalDriverLicense("1235-5345")
.travelerInsurance("Samsung insurance")
.build();
System.out.println("빌더 패턴 적용하기 : " + travelCheckList.toString());
}
// 결과
// 빌더 패턴 적용하기 : TravelCheckList(id=1, passport=M12345, flightTicket=Paris flight ticket, creditCard=Shinhan card, internationalDriverLicense=1235-5345, travelerInsurance=Samsung insurance)
}
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Car {
private String id;
private String name;
**@Builder** // 생성자를 만든 후 그 위에 @Builder 애노테이션 적용
public Car(String id, String name) {
this.id = id;
this.name = name;
}
}
public class CarImpl {
private String id = "1";
private String name = "carTest";
Car car3 = Car.builder()
.id(id)
.name(name)
.build();
}
사실 이 빌더 패턴에 대해서는 개발환경이나 언어적 특성에 따라 긍정적인 반응과 부정적인 반응이 갈리기는 한다.
모든 그렇듯, 무작정 사용하지 말고 한번 자신이 개발하는 전체적인 구조나 환경의 관점에서 장단점을 판단해보고 사용하는 것이 중요한 것 같다 !