Effective Java 3/E 북스터디 기록
아이템2. 생성자에 매개변수가 많다면 빌더를 고려하라
필수 매개변수만 받는 생성자부터 시작하여 필수 매개변수와 선택 매개변수 1개를 받는 생성자, 선택 매개변수를 2개 받는 생성자 ... 선택 매개변수를 전부 다 받는 생성자까지 모든 생성자를 작성하는 방식이다.
자바빈즈 패턴은 선택적 매개변수가 많을 때 활용할 수 있는 두번째 대안이다.
매개변수가 없는 생성자로 객체를 만들고 세터 (Setter) 메서드들을 호출하여 매개변수를 설정한다.
빌더패턴은 점층적 생성자 패턴과 자바빈즈 패턴 두 가지의 장점만을 취한 형태이다.
빌더라는 별도의 객체를 통해 일련의 과정을 거쳐 객체를 생성하게 된다.
클래스 사용자는 직접 객체를 생성하지 않고, 필수 매개변수만으로 빌더 객체를 생성하고, 이 빌더 객체가 제공하는 일종의 세터 메소드를 사용하여 객체를 완성해갈 수 있다.
이때, 빌더 객체의 세터 메소드의 반환값은 빌더 자기 자신이므로 메소드를 연결하여 연속으로 사용하는 메소드 체이닝(Method Chaining)을 할 수 있다.
class Hamburger {
private final int size;
private final int bun;
private final int patty;
private final int lettuce;
private final int tomato;
private Hamburger(Builder builder) {
this.size = builder.size;
this.bun = builder.bun;
this.patty = builder.patty;
this.lettuce = builder.lettuce;
this.tomato = builder.tomato;
}
public static class Builder {
// 필수 매개변수
private final int size;
// 선택 매개변수
private int bun = 0;
private int patty = 0;
private int lettuce = 0;
private int tomato = 0;
public Builder(int size) {
this.size = size;
}
public Builder bun(int bun) {
this.bun = bun;
return this;
}
public Builder patty(int patty) {
this.patty = patty;
return this;
}
public Builder lettuce(int lettuce) {
this.lettuce = lettuce;
return this;
}
public Builder tomato(int tomato) {
this.tomato = tomato;
return this;
}
public Hamburger build() {
return new Hamburger(this);
}
}
}
Hamburger 클래스 내부에 정적 클래스인 Builder 가 정의되어 있는 모습을 볼 수 있다. Builder 클래스는 필수 매개변수인 size 만을 전달받아 생성된다. 그리고 bun, patty, lettuce, tomato 와 같은 메소드는 빌더 자기자신의 매개변수를 설정하고, 자기자신을 반환하는 것을 확인할 수 있다.
마지막으로 build 메소드는 Hamburger 객체를 생성하여 반환하는데, Hamburger 의 매개변수에는 빌더 하나만 전달한다. Hamburger 클래스의 생성자는 Builder 를 전달받아 매개변수를 설정할 수 있다.
위 클래스는 아래와 같이 사용할 수 있을 것 이다.
Hamburger hamburger = new Hamburger.Builder(10)
.bun(2)
.lettuce(3)
.patty(3)
.build();
빌더 패턴도 장점만 존재하지는 않다. 선택적 매개변수를 많이 받는 객체를 생성하기 위해서는 먼저 빌더 클래스부터 정의해야한다. 빌더의 생성비용이 크지는 않지만, 성능에 민감한 상황에서는 문제가 될 수 있다고 한다.
또한 매개변수가 4개보다 적다면, 점층적 생성자 패턴을 사용하는 것이 더 좋다고 한다. 빌더 패턴의 코드가 다소 장황하기 때문이다. 하지만, API 는 시간이 지날수록 많은 매개변수를 갖는 경향이 있다. 따라서 애초에 빌더 패턴으로 시작하는 편이 나을 때가 많다.