스프링으로 Lombok을 사용하면 객체를 생성할 때, @Builder를 통해 객체를 생성하는 경우가 많다.
생성자에 매개 변수가 많을 때, @Builder를 사용하면, 코드를 읽기가 훨씬 쉬워진다.
@Builder
public User(String displayName, String password, String email) {
this.displayName = displayName;
this.password = password;
this.email = email;
}
//new 생성자를 이용한 객체 생성(1)
User user1 = new User("test","1234","test@gmail.com");
//builder를 사용한 객체 생성(2)
User user2 = User.builder().displayName("test")
.password("1234")
.email("test@gmail.com")
.build();
그렇다면, 오늘의 포스팅은 빌더 애노테이션을 사용하지 않고 자바로 코드를 짜서 빌더 패턴을 만들어 보려고 한다.
참고: @Builder는 클래스에 다는 것이 아니라 위의 코드처럼 생성자에 코드에 작성하는 것이 좋다.
this를 이용해서 다시 Builder를 리턴하여 연속으로 메서드를 사용할 수 있게 한다.
public class User {
private String displayName;
private String password;
private String email;
// 그냥 new 키워드로 객체를 생성할 수도 있음.
public User(String displayName, String password, String email) {
this.displayName = displayName;
this.password = password;
this.email = email;
}
// 1)
private User() {}
// 2)
public static Builder builder() {
return new Builder();
}
// 3)
public static class Builder {
//(1)
private User user = new User();
//(2)
public Builder displayName(String displayName) {
user.displayName = displayName;
return this; //Builder를 리턴.
}
//(3)
public Builder password(String password) {
user.password = password;
return this;
}
//(4)
public Builder email(String email) {
user.email = email;
return this;
}
//(5)
public User build() {
return user;
}
}
}
이렇게 만든 패턴을 사용해 보면, 아래와 같이 2가지 형식으로 사용할 수 있다.
//(1)
User user = User.builder().displayName("sdf")
.password("1234")
.email("test@gmail.com")
.build();
//(2)
User.Builder builder = User.builder(); //Builder 객체 생성;
builder.email("test@gmail.com");
builder.password("1234");
builder.displayName("sdf");
User user = builder.build();
(1)과 (2) 모두 표현하는 방식은 다르지만 같은 원리이다.
- builder()를 통해서 Builder 객체를 생성. -> 그 안에서 User 객체 생성.
- Builder 객체에 있는 메서드를 통해 User에 속성 부여 -> (1)의 경우, 메서드의 리턴 값이 Builder이므로 다시 연속으로 메서드를 사용할 수 있다.(chaining)
- 마지막에 build() 메서드로 지금까지 속성을 부여한 User 객체 리턴.