우당탕탕 개발일지

빌더 패턴(Builder Pattern) / 빌더 어노테이션(@Builder) 본문

Spring

빌더 패턴(Builder Pattern) / 빌더 어노테이션(@Builder)

kyunge_ev 2022. 11. 23. 23:16

" 복합 객체의 생성 과정과 표현 방법을 분리하고 동일한 프로세스를 거쳐 다양한 구성의 인스턴스를 만드는 방법 "

  • 생성과 관련된 디자인 패턴 👉 빌더 패턴(Builder Pattern)
  • 복잡한 인스턴스를 조립하여 만드는 구조
    • 복잡한 것을 만들 때는 전체를 한번에 만드는것 보다 작게 분리하여 만든 후 조립하여 합치는 것이 편리
  • 객체를 생성하는 과정 / 객체를 구현하는 방법 이 2가지로 분리

📌 빌더 패턴의 장점

  • 인스턴스 생성 시 인자를 선택적으로 가독성 좋게 넘길 수 있음
    • 필요한 데이터만 넘길 수 있음
  • 인자의 순서가 상관 없음
  • 불필요한 생성자를 만들지 않음
  • 유연성을 확보할 수 있음
  • 불변성을 확보할 수 있음

📌 Builder 사용

" 생성자의 매개변수가 많은 경우 @Builder를 사용해 볼 수 있다. "

1) 매개변수가 있는 생성자 사용

👀 문제 발견!
매개변수를 넘길 때 순서에 맞게 값을 넘겨줘야하고, 불필요한 필드가 있더라도 꼭 넘겨줘야한다.
보통 기본값인 '0'이나 'null'로 넘겨주긴 하는데 이렇게 되면 어떤 필드가 필요한건지 불필요한건지 알기 어렵다.
즉, 가독성이 매우 떨어지게 된다.

public class SupperMarket {
    private int milk;
    private int apple;
    private int ice;
    private int water;

    public SupperMarket(int milk, int apple, int ice, int water) {
        this.milk = milk;
        this.apple = apple;
        this.ice = ice;
        this.water = water;
    }

    public static void main(String[] args) {
        SupperMarket sm = new SupperMarket(2,3,5,6);
    }
}

2) 매개변수가 없는 생성자에 Setter를 사용

👀 문제 발견!
코드가 길어지고, 최종적인 인스턴스를 만들기까지 여러번의 호출을 거쳐야 되기 때문에 자바빈이 중간에 사용되는 경우 안정적이지 않은 상태로 사용될 여지가 있음

public class SupperMarket {
    private int milk;
    private int apple;
    private int ice;
    private int water;

    public void setMilk(int milk) {
        this.milk = milk;
    }

    public void setApple(int apple) {
        this.apple = apple;
    }

    public void setIce(int ice) {
        this.ice = ice;
    }

    public void setWater(int water) {
        this.water = water;
    }

    public static void main(String[] args) {
        SupperMarket sm = new SupperMarket();

        sm.setMilk(2);
        sm.setApple(3);
        sm.setIce(5);
        sm.setWater(6);
    }
}

3) 빌더 사용

  • 생성자, Setter 사용 시 장점을 모두 취할 수 있음
    • 생성자의 '신축성', 자바빈에서의 '가독성'
  • 필요한 객체를 직접 생성하는 대신, 먼저 필수적인 인자들을 생성자에 전부 전달하여 빌더 객체를 만든다.
    그리고 선택 인자들은 가독성이 좋은 코드로 인자를 넘길 수 있다.
    Setter가 없으므로 객체 일관성을 유지하여 불변 객체로 생성할 수 있다.

@Builder 어노테이션

  • Lombok 기능 중 하나로 자동으로 해당 클래스에 빌더를 추가
  • @AllargsConstructor, @NoArgsConstructor 어노테이션과 함께 사용
  • 넘겨야할 인자 값이 많은 경우 생성자 대신 사용
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Board {
    private Long id;
    private String title;
    private String userName;
    private String content;
    
    Board board = Board.builder()
            .id(this.id)
            .title(this.title)
            .userName(this.userName)
            .content(this.content)
            .build();
}