반응형

목차

    빌더 패턴 이란?

    동일한 프로세스를 거쳐 다양한 구성의 인스턴스를 만드는 방법

    빌더 패턴을 사용하면 객체의 생성을 깔금하고 유연하게 할 수 있다.

    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 디자인 패턴

    반응형

    + Recent posts