Effective Java 3/E 2장 생성자에 매개변수가 많다면 빌더를 고려하라
정적 팩터리와 생성자에는 똑같은 제약이 하나 있다.
선택적 매개변수가 많을때 대응이 어렵다.
점층적 생성자 패턴도 쓸 수는 있지만 매개변수가 많아지면 클라이언트 코드를 작성하거나 읽기 어려워 진다.
public class Hello {
private String str;
private String str2;
private String str3;
public Hello(String str) {
System.out.println("Hello str" + str);
}
public Hello(String str, String str2) {
System.out.println("Hello str1, str2" + str + str2);
}
public Hello(String str, String str2) {
System.out.println("Hello str, str3 " + str + str3);
}
public Hello(String str2, String str3) {
System.out.println("Hello str2, str3" + str2 + str3);
}
}
다음으로 매개변수가 많을 때 활용할 수 있는 자바 빈즈 패턴을 보자.
publci class Hello {
private String str;
private String str2;
private String str3;
public void setStr(String str){
this.str = str;
}
public void setStr(String str2){
this.str2 = str2;
}
public void setStr(String str3){
this.str3 = str3;
}
}
자바 빈즈 패턴에서는 점층적 생성자 패턴의 단점들이 보이지 않는다.
인스턴스를 만들기 쉽고 그 결과 더 읽기 쉬워졌다.
하지만 심각한 단점이 있으니 그건 자바 빈즈 패턴에서는 객체 하나를 만들려면 메서드를 여러 개 호출해야 하고 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓인다.
일관성이 무너지는 문제로 인해 자바빈즈 패턴은 클래스를 불변으로 만들 수 없다.
하지만 이러한 문제점들에 대한 대안으로 빌더 패턴이 존재한다.
빌더는 생성할 클래스 안에 정적 멤버 클래스를 만들어두는 게 보통이다.
public class Hello {
private String str;
private String str2;
private String str3;
public Hello() {}
public static class Builder {
private String str;
private String str2;
private String str3;
public Builder() {
}
public setStr(String str) {
this.str = str;
}
public setStr2(String str2) {
this.str2 = str2;
}
public setStr3(String str3) {
this.str3 = str3;
}
public Hello build() {
return new Hello(this);
}
}
private Hello(Builder builder) {
this.str = builder.str;
this.str2 = builder.str2;
this.str3 = builder.str3;
}
}
쓰기 쉽고 읽기 쉬운 빌더 패턴이 나온다.
빌더 패턴은 파이썬이나 스칼라에 있는 명명된 선택적 매개변수를 흉내 낸 것이다.
만들어진 빌더 패턴은 다음과 같이 사용할 수 있다.
Hello hello = new Hello.Builder()
.setStr("He")
.setStr2("ll")
.setStr3("o")
.build();