빌더는 복잡한 Object들을 단계별로 구축할 수 있는 생성 디자인 패턴입니다.
이 패턴을 사용하면, 동일한 구성코드를 사용하여 다양한 타입과 표현을 제공합니다.
객체를 생성하는 대부분의 경우에는 빌더 패턴을 적용하는 것이 좋다.
다음 2가지를 제외하고는 빌더를 구현할 필요가 없다.
- 객체의 생성을 라이브러리로 위임하는 경우
- 변수의 개수가 2개 이하이며, 변경 가능성이 없는 경우
// 1. 더미값을 넣어주는 방법 User user = new User("망나니개발자", 0, 180, 150) // 2. 생성자 또는 정적 메소드를 추가하는 방법 @NoArgsConstructor @AllArgsConstructor public class User { private String name; private int age; private int height; private int iq; public User (String name, int height, int iq) { this.name = name; this.height = height; this.iq = iq; } public static User of(String name, int height, int iq) { return new User(name, 0, 180, 150); } }
User 객체를 생성해야 하는데 age라는 파라미터가 필요 없는 상황이라면, 생성자나 정적 메소드를 이용하는 경우라면 age에 더미 값을 넣어주거나 age가 없는 생성자를 새로 만들어주어야 한다.
반복적인 변경을 필요로 하면서 시간 낭비로 이어지게 된다. 하지만 빌더를 이용하면 동적으로 이를 처리할 수 있다.
User user = User.builder()
.name("망나니 개발자")
.height(180)
.iq(150).build();
// ASIS User user = new User("망나니개발자", 28, 180, 150) // TOBE User user = new User("망나니개발자", 28, 180, 150, 75)
만약 위와 같이 User 객체를 생성하는 코드가 100개 있다면 모든 로직을 수정해주거나 생성자를 따로 추가하는 등의 불필요한 조치를 해주어야 할 것이다. 하지만 빌더 패턴를 기반으로 코드가 작성되어 있다면 기존의 코드는 수정할 필요가 없다. 왜냐하면 빌더 패턴은 유연하게 객체의 값을 설정할 수 있도록 도와주기 때문이다.
빌더 패턴을 사용하면 매개변수가 많아져도 가독성을 높일 수 있다.
생성자로 객체를 생성하는 경우에는 매개변수가 많아질수록 코드 리딩이 급격하게 떨어진다.
예를 들어 다음과 같은 코드가 있다고 하자.
User user = new User("망나니개발자", 28, 180, 150)
위와 같은 코드를 보면 28와 180 또는 150이 무엇을 의미하는지 바로 파악이 힘들고, 클래스 변수가 4개 이상만 되어도 코드를 읽기 힘들어진다. 하지만 다음과 같이 빌더 패턴을 적용하면 직관적으로 어떤 데이터에 어떤 값이 설정되는지 쉽게 파악하여 가독성을 높일 수 있다.
User user = User.builder() .name("망나니 개발자") .age(28) .height(180) .iq(150).build();
수정자 패턴(Setter)를 흔히 사용한다. 하지만 Setter를 구현한다는 것은 불필요하게 변경 가능성을 열어두는 것이다. 유지보수 시에 값이 할당된 지점을 찾기 힘들게 만들며 불필요한 코드 리딩 등을 유발한다. 그렇기 때문에 클래스 변수는 변경 가능성을 최소화하는 것이 좋다.
위의 User 클래스를 다음과 같이 수정할 수 있다.
@Builder
@RequiredArgsConstructor
public class User {
private final String name;
private final int age;
private final int height;
private final int iq;
}
- final을 붙일 수 없는 경우
이러한 경우라면 final이 없어도 Setter를 구현하지 않음으로써 동일한 효과를 얻을 수 있다. 중요한 것은 변경 가능성을 열어두지 않는 것인데, final로 강제할 수 있다면 가장 바람직하지만 final을 붙일 수 없는 경우라면 Setter를 넣어주지 않으면 된다.@Builder @AllArgsConstructor public class User { private String name; private int age; private int height; private int iq; }