# 빌더 (Builder) 패턴

# 빌더 패턴이란 무엇인가요?

복잡한 객체를 생성하는 방법을 정의하는 클래스와 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴입니다.

# 예시 코드

public class Character {    // 클래스 정의
    private String name;    // 닉네임
    private int level;  // 레벨
    private String guild;   // 길드
    private String spouse;  // 배우자
    
    public Character(String name, int level, String guild, String spouse) {
        this.name = name;
        this.level = level;
        this.guild = guild;
        this.spouse = spouse;
    }
    
}

이렇게 클래스를 정의하면, 인스턴스를 생성할 때 데이터 값이 없을 경우에도 매개변수로 null 값을 다 입력해 주어야 합니다.

 Character character = new Character("예시1", 140, null, null)  // 인스턴스 생성

하지만, 빌더패턴을 사용한다면

public class Character {    // 클래스 정의
    private String name;    // 닉네임
    private int level;  // 레벨
    private String guild;   // 길드
    private String spouse;  // 배우자
    
    private Character(Builder builder) {
        this.name = builder.name;
        this.level = builder.level;
        this.guild = builder.guild;
        this.spouse = builder.spouse;
    } 
    
    public static class CharacterBuilder {  // 정적 내부 클래스
        private String name;
        private int level; 
        private String guild;  
        private String spouse;
        
        public CharacterBuilder() {}    // 현재 예시에서는 생성자 부분을 비워놨지만, 이 부분에 필수로 입력해야하는 필드를 집어넣어도 된다.
        
        public CharacterBuilder name(String name) {
            this.name = name;
            return this;
        }

        public CharacterBuilder level(int level) {
            this.level = level;
            return this;
        }
        ... //guild와 spouse도 비슷하게 생성
        
        public Character build() {
            return new Character(this);
        }
    }
    
    
}
Character character = new Character.CharacterBuilder()
                                .name("예시2")
                                .level(200)
                                .guild("빌더패턴")
                                .build();

이런식으로 필요한 데이터값만을 입력하여 인스턴스를 생성할 수 있습니다.

# 생성자 대신에 Setter을 이용하면 빌더패턴을 안써도 되지 않나요?

setter을 사용한다면, 인스턴스의 생성후에도 setter을 이용하여 데이터의 값이 변경될 가능성이 있습니다. 하지만 빌더패턴을 사용한다면 인스턴스의 생성후에 데이터의 값이 변화될 수 없어 안전하고 유지보수에 더 용이합니다.

# 빌더 패턴을 사용하는 경우

  • 매개변수가 많거나 선택 인자가 많을 때 사용하는 것이 좋습니다.

# 빌더 패턴을 사용한 예시

  • java.lang.StringBuilder, StringBuffer
  • 롬복 라이브러리의 @Builder
  • 스프링의 MockMvcWebClientBuilder

# 빌더 패턴의 장점은 무엇인가요?

  • 필요한 데이터만 값을 설정할 수 있어, 테스트를 할 때 용이하고 불필요한 코드의 양을 줄어줍니다.
  • 유연성이 좋아서 새로운 기능을 추가하기 편리합니다.
  • 데이터에 어떤 값이 설정되는지 직관적으로 볼 수 있어, 매개변수가 많아도 가독성이 높습니다.
  • 객체를 할당할 때만 값을 설정할 수 있어, 변경 가능성을 최소화할 수 있습니다.

# 빌더 패턴의 단점은 무엇인가요?

  • 객체를 생성하려면 Builder 객체를 만들어야하기 때문에, 생성자를 사용하는 것에 비해 코드가 복잡해집니다.

# 참고자료

출처: https://mangkyu.tistory.com/163 [망나니개발자]
출처: https://www.jiniaslog.co.kr/article/view?articleId=702 [Jinia's LOG]