생성자 패턴은 우리가 흔하게 사용했던 Constructor이다.
먼저 일반생성자를 보면서 builder가 왜좋은지 알아보자
public class User {
private int userIdx; // 선택
private String name; // 필수
private String part; // 필수
private int age; // 선택
private String email; // 선택
}
User클래스에서 필수적으로 받아야하고, 선택적으로 받아야하는 정보가 있다고 가정해보자
빌더패턴을 사용하지 않는다면, 필수정보만을 매개변수로 갖고 있는 생성자를 또 생성해야한다. 다시말하면 오버로딩을 통해서 생성자를 여러개 만드는 것을 의미한다.
public class User {
private int userIdx;
private String name;
private String part;
private int age;
private String email;
public User(String name, String part) {
this.name = name;
this.part = part;
}
public User(int userIdx, int age, String email) {
this.userIdx = userIdx;
this.age = age;
this.email = email;
}
}
이런 것을 점층적 생성자 패턴이라고도하는데, 코드가 길어지고 지저분해지는 단점이 있다.
User user = new User(1, "이름", "파트", 25, "이메일");
그리고 이렇게 작성하다보면 실수로 순서를 바꿔 넣을수도있고, 나중에 코드를 읽을때 위의 코드를 보고 어떤 필드에 값을 넣은건지 한번에 알아보기가 어렵다.
이런 단점을 보완하기 위해서 setter 메소드를 사용한 자바 빈(Bean)패턴이 고안되었다.
public static void main(String[] args) {
User user = new User();
user.setUserIdx(1);
user.setName("이름");
user.setPart("파트");
user.setAge(25);
user.setEmail("Builder@naver.com");
}
메인문안에다가 사용하는 것인데, 가독성도 좋아지고, 객체 생성하기도 쉬워졌지만 함수 호출1회로 객체를 생성할수없고, 객체의 일관성이 일시적으로 깨질수도있다.
그래서 이런 생성자패턴과 자바 빈 패턴의 장점을 결합한 것이 바로 빌더패턴이다.
public class User {
private int userIdx; // 선택
private String name; // 필수
private String part; // 필수
private int age; // 선택
private String email; // 선택
public static class Builder {
private int userIdx = 1;
private String name = "이름";
private String part = "서버";
private int age = 25;
private String email = "Builder@naver.com";
public Builder(String name, String part) {
this.name = name;
this.part = part;
}
//필수정보를 포함하는 생성자를따로 만들고
public Builder userIdx(int userIdx) {
this.userIdx = userIdx;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public User build() {
return new User(this);
}
}
public User(Builder builder) {
this.userIdx = builder.userIdx;
this.name = builder.name;
this.part = builder.part;
this.age = builder.age;
this.email = builder.email;
}
public static void main(String[] args) {
User user = new Builder("이름", "파트")
.userIdx(1)
.age(25)
.email("Builder@naver.com")
.build();
}
}
User 클래스 안에 내부 static 클래스인 Builder가 존재하고 필수 값인 name, part로 이루어진 생성자를 만들었다.
빌더 패턴은 만들려는 객체를 바로 만들지 않고 클라이언트가 빌더(생성자 또는 static 팩토리)에 필수적인 매개변수를 주면서 호출해 Builder 객체를 얻은 다음 빌더 객체가 제공하는 세터와 비슷한 메소드를 사용해서 부가적인 필드를 채워넣고 최종적으로 build라는 메소드를 호출해서 만들려는 객체를 생성한다.
하지만 빌더 패턴도 역시 단점이 존재한다. 객체를 생성하려면 우선 빌더객체를 생성해야 하고, 다른 패턴들보다 많은 코드를 요구하기 때문에 인자가 충분히 많은 상황에서 이용할 필요가 있다.