복잡한 객체를 생성하는 방법을 정의한 클래스와 표현하는 방법을 정의하는 클래스를 분리하여, 서로 다른 표현이더라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴
직접 Java로 빌더 패턴을 구현할 수 있지만, Lombok 라이브러리를 통해 쉽고 간단하게 빌더 패턴을 적용할 수 있다.
public class Post {
@Builder
public post( ... ) {
}
}
@Builder
@AllArgsConstructor
public class Post {
...
}
public class Post {
private String title;
private String content;
private String writer;
private Long views;
public Post(String title, String content, String writer, Long views) {
this.title = title;
this.content = content;
this.writer = writer;
this.views = views;
}
}
title, content, writer, views를 필드로 가지는 Post 클래스를 통해 빌더 패턴을 적용하여, 빌더 패턴의 장점을 정리해보았다.
위 예제 코드는 모든 필드에 대해서 모두 파라미터로 값을 넘겨야지만 Post 객체를 생성할 수 있다. 만약 writer가 필요없는 경우, content가 필요없는 경우에도 Post 객체를 생성하기 위해서는 생성자 오버로딩을 통해 여러 생성자를 구현해야한다.
public Post(String title, String writer, Long views) {
this.title = title;
this.writer = writer;
this.views = views;
}
public Post(String title, String content, Long views) {
this.title = title;
this.content = content;
this.views = views;
}
이러한 작업이 한 두번이면 상관없지만, 파라미터가 많거나 반복적으로 요구사항이 변경되는 경우라면 번거로울 수 있다.
Post post = Post.builder()
.title("제목입니다.")
.content("내용입니다.")
.views(0L)
.build();
빌더 패턴을 적용하면, 필요한 데이터만 넘겨 객체를 자유자재로 생성할 수 있다.
Post post = new Post("짧은 문장", "긴 문장", "강민성", 0L);
Post post = Post.builder()
.title("짧은 문장")
.content("긴 문장")
.writer("강민성")
.views(0L)
.build();
빌더를 통해 객체를 생성하면 코드 가독성을 높일 수 있다. 생성자로 객체를 생성하는 경우 매개 변수의 순서에 맞추어 데이터를 전달해야하며, 위의 코드에서 "짧은 문장", "긴 문장", "강민성"이 무엇을 의미하는지 파악하기 힘들어 Post 클래스를 왔다 갔다하며 확인해야하는 빈거로움이 생긴다. 이를 빌더를 통해 직관적으로 어느 필드에 어느 값이 설정되는지 파악할 수 있다.
만약 Post 클래스에 부제목을 설정할 수 있도록 subtitle이라는 필드가 추가되었다고 가정하자. 하지만 아래와 같이 이미 생성자를 통해 객체를 만들어놨다면,
Post post1 = new Post("짧은 문장1", "긴 문장1", "강민성1", 0L);
Post post2 = new Post("짧은 문장2", "긴 문장2", "강민성2", 0L);
새롭게 subtitle이 추가되어 기존의 코드를 수정해야하는 상황이 있을 것이다. 하지만 빌더 패턴은 유연하게 객체의 값을 설정할 수 있기 때문에 빌더 패턴을 적용하면, 새로운 필드가 추가되더라도 기존의 코드에는 영향을 주지 않을 것이다.
Setter 메서드를 사용하는 것은 객체의 불필요한 변경 가능성을 열어두는 것이다. 유지 보수시, 값이 할당된 시점을 찾기 힘든 일이 발생한다. final 변수를 사용하여 객체의 불변성을 확보할 수 있다. 만약 값이 할당되는 시점이 객체가 생성되는 시점뿐이라면, 객체에 잘못된 값이 들어왔을 때 빠르게 대처할 수 있을 것이다. 따라서 클래스 내 변수를 final로 선언하고 객체의 생성은 Builder에게 맡기는 것이 좋다.
https://mangkyu.tistory.com/163
https://jung-story.tistory.com/131