반응형
목차
빌더 패턴 이란?
동일한 프로세스를 거쳐 다양한 구성의 인스턴스를 만드는 방법
빌더 패턴을 사용하면 객체의 생성을 깔금하고 유연하게 할 수 있다.
Effective Java의 두번째 규칙의 제목이 바로 생성자의 인자가 많을 때는 빌더(Builder) 패턴을 이용하라
빌더 패턴 아키텍처
가장 중요한 부분은 Director 부분이며 클라이언트는 Director를 거친다.
빌더 패턴 아닌 경우
/**
* 짧은 여행 : 짧은 여행이기 때문에 set해줄게 별로 없음
*/
TourPlan shortTrip = new TourPlan();
shortTrip.setTitle("오레곤 롱비치 여행");
shortTrip.setStartDate(LocalDate.of(2021, 7, 15));
/**
* 긴 여행
*/
TourPlan tourPlan = new TourPlan();
tourPlan.setTitle("칸쿤 여행");
tourPlan.setNights(2); //2박
tourPlan.setDays(3); //3일
tourPlan.setStartDate(LocalDate.of(2020, 12, 9));
tourPlan.setWhereToStay("리조트");
tourPlan.addPlan(0, "체크인 이후 짐풀기");
tourPlan.addPlan(0, "저녁 식사");
tourPlan.addPlan(1, "조식 부페에서 식사");
tourPlan.addPlan(1, "해변가 산책");
tourPlan.addPlan(1, "점심은 수영장 근처 음식점에서 먹기");
tourPlan.addPlan(1, "리조트 수영장에서 놀기");
tourPlan.addPlan(1, "저녁은 BBQ 식당에서 스테이크");
tourPlan.addPlan(2, "조식 부페에서 식사");
tourPlan.addPlan(2, "체크아웃");
문제점
- set 해줘야 하는 값이 꼬일 수있다.
- 2박 3일을 입력하기 위해선 setNights(2), setDays(3) 처럼 입력해야하는데 둘 중 하나를 빼 먹을 수 있다.
- 생성자 초기 선언 할 때 너무 장황하다.
- 그러다 보면 생성자를 조정할 수 있는데, 사용자 입장에서 어떤 생성자를 써야할지 모호해질 수 있다.
더보기

초기 선언이 너무 장황한 예시

빌더 패턴 구현
Interface - TourPlanBulder
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);
/**
* 데이터 검증을 할 수 있음.
* nights, days 중 하나만 들어갔다던지, 근교여행인데 굳이 필요없는 값이 들어간건 아닌지
* @return
*/
TourPlan getPlan(); //데이터 검증
}
Class - DefalutTourBuilder
/**
* 구현체 생성
*/
public class DefaultTourBuilder implements TourPlanBuilder {
private String title;
private int nights;
private int days;
private LocalDate startDate;
private String whereToStay;
private List<DetailPlan> plans;
/**
* this를 리턴한다는 것은 DefaultTourBulder가 리턴이 된다는 뜻
* @param nights
* @param days
* @return
*/
@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;
}
/**
* 마지막에 인스턴스를 생성한다.
* @return
*/
@Override
public TourPlan getPlan() {
return new TourPlan(title, nights, days, startDate, whereToStay, plans);
}
}
TourDirector
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();
}
}
Main
public static void main(String[] args) {
TourDirector director = new TourDirector(new DefaultTourBuilder());
TourPlan tourPlan = director.cancunTrip();
TourPlan tourPlan1 = director.longBeachTrip();
}
빌더 패턴 장점 & 단점
장점
- 빌더 패턴으로 생성자의 복잡함을 단순화 할 수 있다.
단점
자바와 스프링에서 찾아보는 패턴
StringBuffer (Sync 사용)
StringBuffer와 StringBuilder의 차이는 Sync(동기화)여부의 차이가 있다.
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
String result = stringBuilder.append("whiteship").append("keesun").toString();
System.out.println(result);
}
StringBuilder (Sync 미사용)
Stream.Builder
UriComponents howToStudyJava = UriComponentsBuilder.newInstance()
.scheme("http")
.host("www.whiteship.me")
.path("java playlist ep1")
.build().encode();
System.out.println(howToStudyJava);
lombok
@Builder
public class LombokExample {
private String title;
private int nights;
private int days;
public static void main(String[] args) {
LombokExample trip = LombokExample.builder()
.title("여행")
.nights(2)
.days(3)
.build();
}
}
Spring
//URI를 만들어주는 Builder
public static void main(String[] args) {
UriComponents howToStudyJava = UriComponentsBuilder.newInstance()
.scheme("http")
.host("www.whiteship.me")
.path("java playlist ep1")
.build().encode();
System.out.println(howToStudyJava);
}
출처
인프런
김영한-코딩으로 학습하는 GoF 디자인 패턴
반응형
'Java > *****디자인패턴' 카테고리의 다른 글
[싱글톤 패턴] Spring에서 싱글톤을 사용하는 이유 (0) | 2022.05.05 |
---|---|
퍼사드(Facade) 패턴 (0) | 2022.04.03 |
싱글톤 (Singleton) 패턴 (0) | 2022.04.01 |
디자인 패턴 (0) | 2022.03.31 |
디자인 패턴 싱글톤 패턴 개념 정리 (0) | 2022.03.18 |