ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 빌더 패턴
    Java 2022. 4. 9. 00:01

    빌더 패턴이란?

    빌더 패턴은 인스턴스를 생성할 때 생성자(Constructor)만을 통해서 생성하는데 어려움이 있어서 고안된 패턴입니다.

    클래스에 생성자 인자가 많다면 어떠한 인자가 어떠한 값을 나타내는지 알기 어렵기 때문입니다.

     


    예제를 통해서 자세하게 알아보겠습니다.

     

    다음은 User 클래스입니다.

    public class User {
        private int userIdx;   // 선택
        private String name;   // 필수
        private String part;   // 필수
        private int age;       // 선택
        private String email;  // 선택
    }

    만약 User 클래스에서 필수적으로 받아야 하는 정보, 선택적으로 받아야 하는 정보가 있다고 가정해 보겠습니다.

    빌더 패턴을 사용하지 않는다면 일반적으로 점층적 생성자 패턴을 적용합니다.

     

     

    생성자 패턴

    User user = new User(20,"Jun","myPart",20,"0");

    이런 생성자를 사용하다보면 필요 없는 매개변수도 넘겨야 하는 경우가 발생합니다.

    보통 0 같은 기본값을 넘기지만 작성하기도 힘들고 읽기도 어렵습니다.

    예를 들어 해당 인자들이 어떤것을 의미하는지 파악하려면 User 클래스의 내부를 보아야 알 수 있습니다.

     

     

    점층적 생성자 패턴이란?

    필수 인자만 받는 생성자를 만들고, 선택적으로 받는 값의 생성자를 만드는 것입니다.

    즉, 오버로딩을 통해서 생성자를 여러 개 만드는 것을 의미합니다.

    public class User {
        private int userIdx;
        private String name;
        private String part;
        private int age;
        private String email;
    
        public User(String name, String part) {
            this.name = name;
            this.part = part;
        }
    
        public User(int userIdx, int age, String email) {
            this.userIdx = userIdx;
            this.age = age;
            this.email = email;
        }
    }

     

    점층적 생성자 패턴의 단점

    • 코드가 길어지고 지저분해진다.
    • 개발자의 실수가 발생할 수 있습니다. (생성자에 실수로 값의 순서를 바꿔서 넣기)

     

    점층적 생성자 패턴의 단점을 보완하기 위한 자바 빈 패턴 등장

    자바 빈 패턴

    1. 아무런 매개변수를 받지 않는 생성자를 사용하여 인스턴스를 생성합니다.

    2. setter 메서드를 이용해 필요한 필드만 설정합니다.

     

    코드를 통해서 이해해보겠습니다.

    public static void main(String[] args) {
       User user = new User();
       user.setUserIdx(1);
       user.setName("이름");
       user.setPart("파트");
       user.setAge(25);
       user.setEmail("Builder@naver.com");
    }

    가독성은 생성자를 사용한 것보다 훨씬 좋아졌습니다.

     

    자바 빈 패턴의 단점

    • 매번 setter를 이용하여 객체를 생성하다 보니 최종 인스턴스를 만들기 위해서 여러 번의 호출을 거쳐야 합니다. 이때 자바 빈이 중간에 사용되는 경우 안정적이지 않은 상태로 사용될 여지가 존재합니다.
    • setter가 존재하기 때문에 immutable 객체를 생성할 수 없습니다.
    • 쓰레드 안정성을 보장하기 위해서는 추가적인 locking 작업이 필요합니다.

     

     

    객체를 "freezing" 하여 불변 객체로 만드는 방법은 존재하긴 합니다.

    사용자가 직접 Flag라는 변수를 만들고 해당 Flag가 True이면 값을 바꿀 수 없도록 예외를 던지는 방식으로 구현할 수 있습니다.

     

    생성자 패턴 + 자바 빈 패턴의 장점 결합한 빌더 패턴 등장

    필수적인 매개변수와 선택적인 매개변수 조합으로 여러 생성자를 만들 수 있는 빌더 패턴이 등장했습니다.

    생성자의 안정성과 자바빈을 사용할 때 얻을 수 있었던 가독성을 모두 얻게 됩니다.

     

    빌더 패턴을 통해 Python이나 C#에서 제공하는 Named Optional Parameter를 모방할 수 있습니다.

     

    Named Optional Parameter란?

    User user = new User(userIdx : 20, name : "Jun", part : "myPart", age : 20);

    다음과 같이 매개변수에 이름을 명칭하여 선택적으로 사용하는 방법으로 이해하시면 됩니다.

     

    빌드 패턴 예시

      User user = new Builder("이름", "파트")
                    .userIdx(1)
                    .age(25)
                    .email("Builder@naver.com")
                    .build();

     

    빌더 패턴은 만드려는 객체를 바로 만들지 않고 클라이언트는 빌더에 필수적인 매개변수를 주면서 호출하여 Builder 객체를 얻습니다.

     

    이후에 빌더 객체가 제공하는 setter와 비슷한 메서드를 사용하여 부가적인 필드를 채워 넣고 최종적으로 build라는 메서드를 호출하여 만들려는 객체를 생성합니다.

     

    빌더 패턴 예시 코드

    public class User {
        private int userIdx;    // 선택
        private String name;    // 필수
        private String part;    // 필수
        private int age;        // 선택
        private String email;   // 선택
    
    
        public static class Builder {
            private int userIdx;
            private String name ;
            private String part;
            private int age;
            private String email;
    
            public Builder(String name, String part) { //필수 인자인 name,part는 Builder생성할때 넣어줌
                this.name = name;
                this.part = part;
            }
    
    	//선택적인 친구들은 메서드 형식으로 값을 할당하고 자기자신을 반환
            
            public Builder userIdx(int userIdx) {
                this.userIdx = userIdx;
                return this;
            }
            public Builder age(int age) {
                this.age = age;
                return this;
            }
    
            public Builder email(String email) {
                this.email = email;
                return this;
            }
    	//빌드 메서드를 통해 유저 클래스 값 할당
            public User build() {
                return new User(this);
            }
        }
    
        public User(Builder builder) {
            this.userIdx = builder.userIdx;
            this.name = builder.name;
            this.part = builder.part;
            this.age = builder.age;
            this.email = builder.email;
        }
    
        public static void main(String[] args) {
            User user = new User.Builder("이름", "파트")
                    .userIdx(1)
                    .age(25)
                    .email("Builder@naver.com")
                    .build();
        }
    }

     

    빌더 패턴 단점

    객체를 생성하려면 우선 빌더객체를 생성해야 하고, 다른 패턴들보다 많은 코드를 요구하기 때문에 인자가 충분히 많은 상황에서 이용할 필요가 있습니다.

     

     

    Lombok @Builder

    위에서 만든 빌더 클래스를 직접 만들지 않아도 롬복 플러그인이 지원해주는 어노테이션 하나로 클래스를 생성할 수 있습니다.

     

    @Builder
    public class Person {
        private final String name;
        private final int age;
        private final int phone;
    }
    Person person = Person.builder() // 빌더어노테이션으로 생성된 빌더클래스 생성자
        .name("seungjin")
        .age(25)
        .phone(1234)
        .build();

     

    결론

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

    하지만 변경가능성이 적으며 매개변수가 2개 이하인 경우에도 빌더 패턴을 적용하는 것은 불필요할 수 있습니다.

     

    또한 롬복을 사용하여 빌더 패턴을 사용한다면 편리하게 사용할 수 있습니다.

     

     

    출처

    https://devlog-wjdrbs96.tistory.com/207

     

    [Java] 빌더 패턴(Builder Pattern)

    1. 빌더 패턴(Builder pattern) Builder 패턴은 인스턴스를 생성할 때 생성자(Constructor)만을 통해서 생성하는데는 어려움이 있어서 고안된 패턴이다. 클래스에 생성자 인자가 많다면 Builder 패턴을 사용

    devlog-wjdrbs96.tistory.com

    https://www.youtube.com/watch?v=OwkXMxCqWHM&t=29s 

    https://esoongan.tistory.com/82

     

    [JAVA] 빌더패턴 (Builder Pattern) , @Builder

    entity나 Dto객체에 값을 넣어줄때 롬복의 빌더 애노테이션(@Builder)을 종종 사용하곤 하는데 완벽히 이해를 하지 못한것같아 정리해보았다! 빌더패턴이란? 디자인패턴중 하나로, 생성과 표현의 분

    esoongan.tistory.com

    https://m.cafe.daum.net/csharp-novice/5ijJ/70

     

    4.15 홀로 사용되는 this(return this)

     

    m.cafe.daum.net

     

    'Java' 카테고리의 다른 글

    Java는 왜 Pure OOP가 아닐까?  (0) 2022.05.10
    객체지향 5원칙 : SOLID  (0) 2022.04.22
    [Java] 프록시 패턴이란?  (0) 2022.04.08
    [Java] 리플렉션이란?  (0) 2022.04.07
    [Java] 직렬화(Seralize)란?  (0) 2022.03.24

    댓글

Designed by Tistory.