Book Record/Effective Java 3E

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

lakelight 2022. 11. 30. 16:00
728x90
반응형

 

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


점층적 생성자 패턴

생성자의 매개변수의 개수를 조절하여 객체를 생성하는 방식입니다. 이 방식은 매개변수의 순서도 중요하고 매개변수가 무엇을 의미하는지 알기도 어렵기 때문에 작성하기 어렵습니다.

public class TestClass {
    
    private int x;
    private int y;
    private int z;

    public TestClass(int x) {
        this.x = x;
    }

    public TestClass(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public TestClass(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public static void main(String[] args) {
        TestClass x = new TestClass(1);
        TestClass xy = new TestClass(1, 2);
        TestClass xyz = new TestClass(1, 2, 3);
    }
}
확장하기 어렵다는 단점이 있습니다.

 

자바빈즈 패턴

매개변수가 없는 생성자로 객체를 만든 후, 세터 메서드들을 호출해 원하는 매개변수의 값을 설정하는 방식입니다.

public class TestClass {

    private int x = 0;
    private int y = 0;
    private int z = 0;

    public TestClass() {
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setZ(int z) {
        this.z = z;
    }

    public static void main(String[] args) {
        TestClass testClass = new TestClass();
        testClass.setX(1);
        testClass.setY(2);
        testClass.setZ(3);
    }
}
객체 하나를 만들려면 메서드를 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓이게 됩니다. 또한 클래스를 불변으로 만들 수 없습니다.

 

빌더 패턴

점층적 생성자 패턴의 안전성과 자바 빈즈 패턴의 가독성을 겸비한 패턴입니다. 클라이언트가 직접 객체를 만드는 대신, 필수 매개변수만으로 생성자를 호출해 빌더 객체를 얻습니다.

public class TestClass {

    private final int x; // 필수 불변 매개 변수
    private final int y;
    private final int z;

    public static class Builder{
        private final int x;
        private final int y;
        private int z = 0;

        public Builder(int x, int y) {
            this.x = x;
            this.y = y;
        }
        
        public Builder z(int z){
            this.z = z;
            return this;
        }
        
        public TestClass build(){
            return new TestClass(this);
        }
    }
    
    private TestClass(Builder builder){
        x = builder.x;
        y = builder.y;
        z = builder.z;
    }

    public static void main(String[] args) {
        TestClass xyz = new Builder(1, 2).z(3).build();
        TestClass xy = new Builder(1, 2).build();
    }
}
빌더 패턴은 계층적으로 설계된 클래스와 함께 쓰기 좋습니다. 

 

 

마무리

프로젝트를 할 때 @Builder 어노테이션을 통해 빌더 패턴을 주로 사용했었는데
직접 구현하는 코드를 보니 더 활용을 잘 할 수 있을 것 같습니다.

빌더 생성 비용이 크지는 않지만 성능에 민감한 상황에서는 주의를 해야하며,
코드가 장황해서 매개변수가 4개 이상일 때 사용해야 가치가 있다는 점을 알게되었습니다.

여기까지 포스팅 읽어주셔서 감사합니다.

 

[출처]

이펙티브 자바 Effective Java 3/E - 조슈아 블로크 저/ 개앞맵시 

 

728x90
반응형