빌더 패턴을 사용하기 전 어떠한 패턴들이 존재했는지?

 

1. 점층적 생성자 패턴 (Telescoping Constructor Pattern)

 

선택적 인자가 많은 객체를 생성할 때 '점층적 생성자 패턴'을 사용한다. 필요한 매개변수에 맞춰서 상황마다 생성자를 늘리는 방식

 

public class TelescopingConstructorPattern {

    private int userSeq;
    private String userName;
    private String userId;
    private int userAge;
    private String userEmail;

    public TelescopingConstructorPattern(int userSeq) {
        this.userSeq = userSeq;
    }

    public TelescopingConstructorPattern(int userSeq, String userName) {
        this.userSeq = userSeq;
        this.userName = userName;
    }

    public TelescopingConstructorPattern(int userSeq, String userName, String userId) {
        this.userSeq = userSeq;
        this.userName = userName;
        this.userId = userId;
    }

    public TelescopingConstructorPattern(int userSeq, String userName, String userId, int userAge) {
        this.userSeq = userSeq;
        this.userName = userName;
        this.userId = userId;
        this.userAge = userAge;
    }

    public TelescopingConstructorPattern(int userSeq, String userName, String userId, int userAge, String userEmail) {
        this.userSeq = userSeq;
        this.userName = userName;
        this.userId = userId;
        this.userAge = userAge;
        this.userEmail = userEmail;
    }

}

 

public class CallerClass {
		//호출 방식
        TelescopingConstructorPattern tcp = new TelescopingConstructorPattern(1,"name","id",1,"email");

}

단점으로는 사용자가 원하지 않는 매개변수도 지정해야 하며, 매개변수 조합에 따라 생성자 수가 증가한다.
그러므로 코드 작성 및 가독성이 저하된다.

 

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

 

매개변수가 없는 생성자를 생성 후 setter 메서드들을 호출하여 원하는 매개변수 값을 설정하는 방식

 

public class JavaBeansPattern {

    private int userSeq;
    private String userName;
    private String userId;
    private int userAge;
    private String userEmail;

    public JavaBeansPattern() { }

    public void setUserSeq(int userSeq) {
        this.userSeq = userSeq;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public void setUserAge(int userAge) {
        this.userAge = userAge;
    }

    public void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }
    
}
public class CallerClass {
    public static void main(String[] args) {
    	//호출 방식
        JavaBeansPattern javaBeansPattern = new JavaBeansPattern();
        javaBeansPattern.setUserSeq(1);
        javaBeansPattern.setUserName("name");
        javaBeansPattern.setUserId("id");
        javaBeansPattern.setUserAge(1);
        javaBeansPattern.setUserEmail("email");
    }
}

 

장점은 점층적 생성자 패턴에 비해 인스턴스를 만들기 쉽다. 가독성이 좋다.

 

단점은 객채 하나를 위하여 여러 메서드를 호출하여야 함, 객체를 완전히 생성하기 전까지는 일관성(consistency)이 무너진 상태에 존재함

 

앞에 두가지 패턴에 비해서 빌더 패턴은 뭐가 좋은 건가?

 

3. 빌더 패턴 (Builder Pattern)

 

필수 매개변수는 생성자를 통해 빌더 객체를 얻은 후 선택 매개변수는 세터 메서드들로 설정하여 build 메서드를 호출하는 점층적 생성자 패턴안정성자바 빈즈 패턴가독성을 가지고 있음.

 

public class BuilderPattern {

    private int userSeq;
    private String userName;
    private String userId;
    private int userAge;
    private String userEmail;

    public BuilderPattern(int userSeq, String userName, String userId, int userAge, String userEmail) {
        this.userSeq = userSeq;
        this.userName = userName;
        this.userId = userId;
        this.userAge = userAge;
        this.userEmail = userEmail;
    }

    public static class Builder {
        private int userSeq;
        private String userName;
        private String userId;
        private int userAge;
        private String userEmail;

        public Builder userSeq(int userSeq) {
            this.userSeq = userSeq;
            return this;
        }

        public Builder userName(String userName) {
            this.userName = userName;
            return this;
        }

        public Builder userId(String userId) {
            this.userId = userId;
            return this;
        }

        public Builder userAge(int userAge) {
            this.userAge = userAge;
            return this;
        }

        public Builder userEmail(String userEmail) {
            this.userEmail = userEmail;
            return this;
        }

        public BuilderPattern build() {
            //필수 멤버변수에 값이 할당되지 않으면 예외처리
            if(userSeq == 0 || userName == null || userId == null || userAge == 0 || userEmail == null) {
                throw new IllegalStateException("Cannot create BuilderPattern");
            }

            return new BuilderPattern(userSeq, userName, userId, userAge, userEmail);
        }
    }
}
public class CallerClass {
    public static void main(String[] args) {
    	//호출 방식
        BuilderPattern bp = new BuilderPattern.Builder()
        	.userSeq(1)
            .userAge(1)
            .userName("name")
            .userId("id")
            .userEmail("email")
            .build();
    }
}

 

장점은 인스턴스를 생성할 때 인자를 선택적으로 가독성 좋게 넘길 수 있음, 인자의 순서에 상관이 없음, 불필요한 생성자가 추가로 필요하지 않음

 

단점은 성능에 민감한 상황에서는 문제가 될 수 있음, 코드가 자바 빈즈 패턴처럼 장황해짐, 요구하는 매개변수가 많아지는 경향이 있다면 코드가 비대해짐

 

마무리

 

정리를 하면 빌더 패턴이 나아보임, 추후 Lombok을 위해 알아야 할거 같아서 정리함