관리 메뉴

버리야 날자

[Effective Java] 생성자의 매개변수가 많을 때는 빌더(builder)를 고려하자. 본문

나만의 작업/Java

[Effective Java] 생성자의 매개변수가 많을 때는 빌더(builder)를 고려하자.

버리 버리야 2009.07.31 11:05
Static 팩토리 메소드와 생성자의 공통적인 제약은 선택 가능한 매개변수가 많아질 경우 신축성 있게 처리하지 못한다는 것인데, 흔히 나도 그러한데 텔리스코핑 생성자(telescoping constructor)패턴을 사용한다. 
필수 매개변수들만 갖는 생성자, 필수 매개변수들과 선택 매개변수 하나를 갖는 생성자, 선택 매개변수 두개를 갖는 생성자 등등의 형태로 오버로딩을 통해 여러개의 생성자를 겹겹이 만드는 것이다.

public class User{
    private String id;
    private String pw;
    private String address;
    // .......15 more field

    public User(String id, String pw){
         this(id, pw, null);
    }
    
    public User(String id, String pw, String address){
        this(id,pw,address);
    }
     //..... more constructor
}

이런식으로 필요한 매개변수만큼의 생성자를 만드는 방법.
매개변수가 몇개 안된다면 문제가 그리 되지 않지만 많으면 많을수록 가독성도 떨어지고 생성자를 찾아가고 또 찾아가고는 하다보면 실수를 유발할 수도 있다.

그럼 자바빈즈(JavaBeans)패턴 사용은 어떨까?

Class에 Setter method를 만들고, 
User user = new User();
user.setId("id");
user.setPw("pw");
user.setAddress("address");
...//more setter method

코드는 길어지지만 인스턴스 생성이 간단하고 코드의 가독성도 좋다..
하지만, 단점은 불변(immutable) 클래스를 만들 수 있는 가능성을 배제하고 스레드(thread)에서 안정성을 유지하려면 다른 작업이 필요하다. 

그럼 조금 더 우아한 방법은? Builder pattern!

public class NutritionFacts {
    public class Builder {
        public Builder(String name, int servingSize,  int servingsPerContainer) { ... }
        public Builder totalFat(int val) { ... }
        public Builder saturatedFat(int val) { ... }
        public Builder transFat(int val) { ... }
        public Builder cholesterol(int val) { ... }
        ... // 15 more setters

        public NutritionFacts build() {
                   return new NutritionFacts(this);
       }
    }
    private NutritionFacts(Builder builder) { ... } 
    }
}

이렇게 선언을 해놓고
NutritionFacts twoLiterDietCoke = new NutritionFacts.Builder("Diet Coke", 240, 8).sodium(1).build();

Builder의 setter method는 연속적으로 여러 번 호출될 수 있도록 빌더 자신의 객체를 반환한다.
코드 작성도 쉽고 가독성도 좋다!!!! 
생성자처럼 빌더는 자신의 매개변수에 불변규칙(invariants : 매개 변수나 필드가 가질 수 있는 값의 약속된 범위나 타입 및 형태를 말한다.)을 적용할 수 있고 build method는 불변 규칙을 검사할 수 있다. 
매개변수들의 값이 빌더로부터 객체에 복사된 후 빌더의 필드가 아닌 객체의 필드에 대해 불변 규칙 검사를 수행된다.

또 다른 장점은 여러개의 가변인자(varargs) 매개변수를 가질 수 있고, 유연성이 좋다. 

단점은, 어떤 객체를 생성하려면 우선 그것의 빌더를 생성해야 하기 때문에 빌더 객체의 생성 비용이 많이는 아니지만 성능이 매우 중요한 상황에서는 문제가 될 수 있다. 

결론은 생성자나 static 팩토리 메소드에서 많은 매개변수를 갖게 될 클래스를 설계할 때 빌더 패턴이 좋다는거~~위의 두 패턴보다 가독성도 좋고 자바빈즈 패턴보다 안전하다는 거~~


참고 
Effective Java 2nd book

Effective Java Reloaded : http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-1512.pdf?






3 Comments
댓글쓰기 폼