Woopii Vyeolog

[디자인 패턴] Build Pattern, 빌더 패턴 본문

java

[디자인 패턴] Build Pattern, 빌더 패턴

WooPii 2021. 2. 24. 23:16

1. 빌더 패턴을 사용하는 이유

  • 불필요한 생성자를 만들지 않고, 객체를 생성
  • 데이터의 순서에 상관없이 객체를 생성
  • 명시적이고, 이해하기 쉬움
  • 유지 보수가 편함

 

즉 빌더 패턴은 객체 생성을 깔끔하고, 유연하게 하기 위한 기법

 

2. [점층적 생성자 패턴] -> [자바빈 패턴] -> [빌더 패턴]

 

2-1. 점층적 생성자 패턴 : 모든 인자를 받는 경우의 생성자를 만든다.

 

단점

  • 다른 생성자를 호출하는 생성자가 많아질 경우, 인자가 추가될 때 코드 수정이 어렵다.
  • 코드 가독성이 떨어진다 (인자 수가 많은 생성자의 경우, 코드만 보고 의미를 해석하기 어렵다.) 

2-2. 자바빈 패턴 :  setter 메소드를 이용하여 객체에 값을 세팅한다.

 

단점

  • 객체 일관성이 깨진다 : 1회의 호출로 객체 생성이 끝나지 않는다. (한번 생성한 객체에 값을 계속 세팅함)
  • 변경 불가능 클래스를 만들수가 없음 : 스레드 안전성을 확보하려면 점층적 패턴보다 많은 일을 해야한다.  

위의 두 패턴의 대안으로서 나온 패턴이 빌더 패턴이다.

 

 

Book.java

package com.example.demo.book.domain;

import java.time.LocalDateTime;
import java.util.Objects;

public class Book {

    private String title;
    private String author;
    private LocalDateTime publishedAt;
    private int pageCount;

    //------------------------------------------------ 점층적 생성자 패턴 ------------------------------------------------
    public Book() {

    }

    public Book(String title) {
        this.title = title;
    }

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    public Book(String title, String author, LocalDateTime publishedAt) {
        this.title = title;
        this.author = author;
        this.publishedAt = publishedAt;
    }

    public Book(String title, String author, LocalDateTime publishedAt, int pageCount) {
        this.title = title;
        this.author = author;
        this.publishedAt = publishedAt;
        this.pageCount = pageCount;
    }
    //------------------------------------------------ 점층적 생성자 패턴 ------------------------------------------------

    //------------------------------------------------ 자바빈 패턴 ------------------------------------------------
    public String getTitle() {
        return this.title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return this.author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public LocalDateTime getPublishedAt() {
        return this.publishedAt;
    }

    public void setPublishedAt(LocalDateTime publishedAt) {
        this.publishedAt = publishedAt;
    }

    public int getPageCount() {
        return this.pageCount;
    }

    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }

    public Book title(String title) {
        setTitle(title);
        return this;
    }

    public Book author(String author) {
        setAuthor(author);
        return this;
    }

    public Book publishedAt(LocalDateTime publishedAt) {
        setPublishedAt(publishedAt);
        return this;
    }

    public Book pageCount(int pageCount) {
        setPageCount(pageCount);
        return this;
    }
    //------------------------------------------------ 자바빈 패턴 ------------------------------------------------
    
    //------------------------------------------------ 빌더 패턴 ------------------------------------------------
    //Builder Class에서 호출
    public Book(BookBuilder bookBuilder) {
        title = bookBuilder.title;
        author = bookBuilder.author;
        publishedAt = bookBuilder.publishedAt;
        pageCount = bookBuilder.pageCount;
    }

    public static class BookBuilder {
        //필수 인자
        private String title;

        //선택적 인자
        private String author = "";
        private LocalDateTime publishedAt = LocalDateTime.now();
        private int pageCount = 0;

        public BookBuilder (String title) {
            this.title = title;
        }

        public BookBuilder author(String value) {
            author = value;
            return this;    //return this로 하면 .으로 인자를 연속적으로 세팅할 수 있다. 
        }

        public BookBuilder publishedAt(LocalDateTime value) {
            publishedAt = value;
            return this;
        }

        public BookBuilder title(int value) {
            pageCount = value;
            return this;
        }

        public Book build() {
            return new Book(this);
        }
    }
    //------------------------------------------------ 빌더 패턴 ------------------------------------------------

    @Override
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof Book)) {
            return false;
        }
        Book book = (Book) o;
        return Objects.equals(title, book.title) && Objects.equals(author, book.author) && Objects.equals(publishedAt, book.publishedAt) && pageCount == book.pageCount;
    }

    @Override
    public int hashCode() {
        return Objects.hash(title, author, publishedAt, pageCount);
    }

    @Override
    public String toString() {
        return "{" +
            " title='" + getTitle() + "'" +
            ", author='" + getAuthor() + "'" +
            ", publishedAt='" + getPublishedAt() + "'" +
            ", pageCount='" + getPageCount() + "'" +
            "}";
    }
}

 

 

test 클래스

 

package com.example.demo;

import java.time.LocalDateTime;

import com.example.demo.book.domain.Book;

import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class BuilderPatternTest {
    
    @Test
    public void Test() {

        System.out.println("-------------점층적 생성자 패턴(telescope constructor pattern)-----------\n");

        Book book1 = new Book("홍길동전");
        Book book2 = new Book("홍길동전","허균");
        Book book3 = new Book("홍길동전","허균",LocalDateTime.now());
        Book book4 = new Book("홍길동전","허균",LocalDateTime.now(),0);

        System.out.println(book1.toString() + "\n");
        System.out.println(book2.toString() + "\n");
        System.out.println(book3.toString() + "\n");
        System.out.println(book4.toString() + "\n");

        System.out.println("-------------자바빈 패턴-----------\n");

        Book book5 = new Book();
        book5.setTitle("홍길동전");
        book5.setAuthor("허균");
        book5.setPublishedAt(LocalDateTime.now());
        book5.setPageCount(0);

        System.out.println(book5.toString() + "\n");

        System.out.println("-------------빌더 패턴-----------\n");

        //builder 생성자 안쪽은 필수 요소를 입력, 선택적 요소는 . 을 통해서 값을 세팅 해준다.
        Book book6 = new Book.BookBuilder("홍길동전")
                            .author("허균")
                            .build();
        System.out.println(book6.toString() + "\n");
    }
}

 

 

'java' 카테고리의 다른 글

[Java] Socket 통신, TCP Client 샘플  (0) 2022.04.02
[Java] Socket 통신, Tcp Server 샘플  (0) 2022.04.02
Vector vs Arraylist  (0) 2020.02.28
String, StringBuffer, StringBuilder  (0) 2020.02.19
garbage collecter  (0) 2020.02.19
Comments