Java

[Effective Java] Item02. 생성자에 매개변수가 많다면 빌더(Builder)를 고려하라

Item02. 생성자에 매개변수가 많다면 빌더(Builder)를 고려하라

 

- 정적 팩터리 메서드와 생성자는 선택적 매개변수가 많을 때 적절히 대응하기가 어렵다.

- 이를 보완하기 위해 많은 개발자들은 다음과 같은 방식을 사용했다.

 

1. 점층적 생성자 패턴(telescoping constructor pattern)

- 필수 매개변수만 받는 생성자 / 필수 매개변수 + 선택적 매개변수 1개를 받는 생성자 / 필수 매개변수 + 선택 매개변수 2개를 받는 생성자 / ... 와 같이 점층적인 형태의 생성자를 여러 개 늘리는 방식

- 단점 : 선택적 매개변수에도 기본값을 지정해야한다, 매개변수 개수가 많아지면 코드 작성, 읽기에 어렵다(각 값의 의미가 뭔지 모름)

 

2. 자바빈즈 패턴(JavaBeans pattern)

- 매개변수가 없는 생성자로 객체를 만든 후, setter를 통해 값을 설정하는 방식

- 단점 : 객체 하나를 만들기 위해 setter를 여러 번 호출해야한다,

객체의 일관성(consistency)이 무너진다 -> setter가 열려있으므로 클래스를 불변을 만들 수 없다 -> 불변 클래스로 만들 수 없다

 

 

 

! 선택적 매개변수가 많을 때에는 점층적 생성자 패턴의 일관성(안전성) + 자바빈즈 패턴의 가독성을 모두 챙길 수 있는 빌더(Builder) 패턴을 사용하자.

 

1. 필수 매개변수만으로 생성자 or 정적 팩터리 메서드를 호출해 Builder 객체를 생성한다.

2. 빌더 객체가 제공하는 일종의 setter 메서드를 통해 원하는 선택 매개변수들의 값을 설정한다. (이 때 메서드의 반환값은 자기자신(빌더))

3. 매개변수가 없는 build() 메서드를 호출해 원하는 객체를 반환한다. 

 

* 일반적으로 빌더는 생성할 클래스 안에 정적 멤버 클래스로 만든다.

public class Foo {
    public static class Builder {
        ...
    }
}

 

- 플루언트(fluent) API, 메서드 연쇄(method chaining) : 빌더의 setter 메서드는 빌더 자신을 반환하므로 연쇄적으로 호출할 수 있다.

- 잘못된 매개변수를 발견하기 위해서는 빌더의 생성자와 setter 메서드에서 입력 매개변수를 검사하고, build 메서드가 호출하는 생성자에서 여러 매개변수에 걸친 *불변식(invariant)을 검사해야 한다.

* 불변식(invarient) : 프로그램이 실행되는 동안 or 정해진 기간 동안 반드시 만족해야 하는 조건

 

 

 

! 빌더 패턴은 계층적으로 설계된 클래스와 함께 쓰기 좋다.

 

- 각 계층의 클래스에 멤버로 빌더를 정의 (추상 클래스 -> 추상 빌더 / 구체 클래스 -> 구체 빌더)

- 시뮬레이트한 셀프 타입 (simulated self-type) 관용구 : self 타입이 없는 자바를 위한 우회 방법으로 추상 메서드인 self를 더해 하위 클래스에서 형변환 없이 메서드 연쇄를 지원

공변 반환 타이핑 (covariant return typing) : 하위 클래스 메서드가 상위 클래스가 정의한 반환 타입이 아닌 그 하위 타입을 반환하는 기능

- 가변인수(varargs) 매개변수 여러개의 사용 : 한 메서드를 여러번 호출하고, 호출 때 넘겨진 매개변수를 하나의 필드로 모을 수 있다.

 

 

 

! 빌더 패턴에 장점만 있는 것은 아니다.

 

- 빌더 생성 비용이 크지는 않지만 성능에 민감한 상황에서는 문제가 될 수 있다

- 코드가 장황해 매개변수 4개 이상에서 사용하자 (하지만 API는 시간이 지날수록 매개변수가 많아지는 경향이 있다)

 

 

소스코드 : https://github.com/HunSeongPark/effective-java/tree/master/src/main/java/item02

 

GitHub - HunSeongPark/effective-java: 책 Effective Java 3/E 공부

책 Effective Java 3/E 공부. Contribute to HunSeongPark/effective-java development by creating an account on GitHub.

github.com