java

Java_Chapter?_builder pattern

강용민 2022. 10. 6. 18:28

builder pattern

빌더 패턴은 생성패턴 중 하나로 객체 지향 프로그래밍에서의 다양한 생성 문제에 대한 유연한 해결책을 제공하기 위해 설계된 디자인 패턴이다.

복잡한 객체를 생성하는 방법을 정의하는 클래스와 해당 클래스를 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴이다.

 

장점

  • 유연성을 확보할 수 있다.
  • 생성 시 가독성을 높일 수 있다.
  • 변경 가능성을 최소화할 수 있다.

 

점층적 생성자 패턴

public class User {
    //required parameters
    private String email;
    private String passwd;
    
    //optional parameters
    private String name;
    private int age;
    
    //AllArgs 생성자
    public UserBuilder(String email, String passwd, String name, int age) {
        this.email = email;
        this.passwd = passwd;
        this.name = name;
        this.age = age;
    }
    
    //requiredArgs 생성자
    public User(String email, String passwd){
        this(email,passwd,"홍길동",25);
    }
}

public class create{
    public static void main(String[] args){
        User user1 = new User();
        User user2 = new User("곽두팔@tistory.com","1234","곽두팔",25);
        User user3 = new User("홍길동@tisotry.com","5678");
    }
}

 

다음 코드는 User 클래스를 바탕으로 생성자와 수정자를 만들었다.

이러한 작업이 한 두번이면 상관 없지만 요구사항은 계속 변하게 되어있고, 반복적인 변경을 필요로 하면서 시간 낭비로 이어지게 된다.

또한 인자값이 많을 수록 객체 생성 시 코드 가독성도 떨어진다.

하지만 이를 빌더를 이용하면 동적으로 이를 처리할 수 있다.

 

빌더 패턴

public class User {
    //required parameters
    private String email;
    private String passwd;
    
    //optional parameters
    private String name;
    private int age;

    
    private User(UserBuilder builder){
    	this.email = builder.email;
        this.passwd = builder.passwd;
        this.name = builder name;
        this.age = builder.age;
    }
    
    public class UserBuilder{
        //required parameters
        private String email;
        private String passwd;

        //optional parameters
        private String name = "홍길동";
        private int age = 25;

        public UserBuilder(String email, String passwd){
            this.email = email;
            this.passwd = passwd;
        }

        public UserBuilder setName(String name){
            this.name = name;
            return this;
        }

        public UserBuilder setAge(int age){
            this.age = age;
            return this;
        }

        public User build(){
            return new User(this);
        }
    }
}



public class create{
    public static void main(String[] args){
        User user = new User.UserBuiler("홍길동@tistory.com","1234")
                    .setName("홍길동")
                    .setAge(25)
                    .build();
    }
}

다음 코드는 User 클래스에 UserBuilder 클래스를 넣어 빌더 패턴으로 만든 형식이다.

객체 생성 시 각 인자가 어떤 의미인지 알기 쉬워진것을 볼 수 있다.

또한 한 번에 객체를 생성하므로 객체 일관성이 깨지지 않으며, setter 메소드가 없으므로 변경 불가능 객체를 만들 수 있다.

 

객체를 생성하는 대부분의 경우에는 빌더 패턴을 적용하는 것이 좋다.

물론 예외적인 케이스가 있을 수 있는데, 대표적으로 크게 다음의 2가지 상황에서는 빌더를 구현할 필요가 없다.

  • 객체의 생성을 라이브러릴로 위임하는 경우
  • 변수의 개수가 2개 이하이며, 변경 가능성이 없는 경우

변수의 개수와 변경 가능성 등을 중점적으로 보고 빌더 패턴을 적용할 지 판단하면 된다.

 

Lombok @Builder

이런 스타일의 빌더 패턴이라면 롬복의 @Builder 애노테이션으로 쉽게 사용할 수 있다.

public class User {
    //required parameters
    @NotBlank
    private String email;
    @NotBlank
    private String passwd;
    
    //optional parameters
    private String name;
    private int age;
    
    //AllArgs 생성자
    @Builder
    public User(String email, String passwd, String name, int age) {
        this.email = email;
        this.passwd = passwd;
        this.name = name;
        this.age = age;
    }
}

public class create{
    public static void main(String[] args){
        User user = User.builder("홍길동@tistory.com","1234").
            .name("홍길동")
            .age(25)
            .build();
            
            
        User.UserBuilder builder = User.UserBuilder("곽두팔@tistory.com","5678");
        builder.name("곽두팔");
        User user = builder.build();
    }
}

주의할 점은 클래스 선언부에 @Builder를 가급적 자제하는 것이다.

@Bbuilder를 클래스에 달아주면 @AllArgsConstructor도 같이 달아주는 것과 같기 떄문에 바람직하지 않다.

가급적 직접 만든 생성자에 달아주는 것이 낫다.

 

[참고]

https://mangkyu.tistory.com/163

https://readystory.tistory.com/121

https://johngrib.github.io/wiki/pattern/builder/#%EC%A0%90%EC%B8%B5%EC%A0%81-%EC%83%9D%EC%84%B1%EC%9E%90-%ED%8C%A8%ED%84%B4

'java' 카테고리의 다른 글

java_Chapter08_예외처리  (0) 2023.03.10
Java_Chapter08_객체 지향 4대 요소  (0) 2022.10.09
Java_Chapter07_클래스의 관계  (0) 2022.09.15
Java_Chapter06_클래스와 객체  (0) 2022.09.14
Java_Chapter05_배열  (0) 2022.09.06