회사에서도, 친구들과의 대화에서 각각 한번씩 언급되었던 것이 빌더 패턴이었다. 대부분의 상황은 나는 주로 빌더패턴을 많이 사용했고, 이에 대해 반대하는 것이었다. 빌더 패턴은 객체를 생성하는 방법 중에 하나이다. 여러 대화를 하다보니, 내가 사실 그동안 빌더패턴을 사용한 것이 장점이 있어라기 보다는 습관적인 행동이었다는 것을 깨달았고, 이제라도 각각 어떤 장단점이 있는지 간단하게 정리해보려고 한다.
객체를 생성하는 방법은 보통 3가지로 알려져있다.
1. 점층적 생성자 패턴
2. 자바빈즈 패턴
3. 빌더 패턴
각각의 생성 형태를 비교하자면,
User user = new User("유저1", "1234", "email1", 0L);
userRepository.save(user);
User user = new User();
user.setUserId("유저1");
user.setUserPassword("1234");
user.setEmail("email1");
user.setMoney(0L);
userRepository.save(user);
매개 변수가 없는 생성자(기본 생성자)로 객체를 만든 후, setter 메서드를 호출하여 원하는 매개변수의 값을 설정하는 방식이다.
User user = User.builder()
.userId("유저1")
.userPassword("1234")
.email("email1")
.money(0L)
.build();
userRepository.save(user);
복잡한 객체의 생성 과정과 표현 방법을 분리하여 다양한 구성의 인스턴스를 만드는 생성 패턴이다.
생성자에 들어갈 매개 변수를 메서드로 하나하나 받아들이고 마지막에 통합 빌드해서 객체를 생성하는 방식이다.
= 별도의 Builder 클래스를 만들어 메소드를 통해 step-by-step 으로 값을 입력받은 후에 최종적으로 build() 메소드로 하나의 인스턴스를 생성하여 리턴하는 패턴이다.
메소드 체이닝을 통해 구현된다.
장점
구현이 간단하고 직관적이다
단점
1) 매개변수가 많아질수록 많은 조합이 만들어지고, 생성자의 수가 많아진다.
2) 초기화하고 싶은 필드만 포함한 생성자가 존재하지 않을 경우 원치 않는 필드까지 매개변수에 값을 지정해줘야 한다.
장점
1) 구현이 간단하고 가독성이 좋다
2) setter 메서드를 통해 유연하게 객체의 상태를 변경할 수 있다.
단점
1) 객체 생성과 초기화가 분리되어 객체의 무결성을 보장하기 어려울 수 있다.
2) setter 메서드가 있기 때문에 객체가 불변성을 가지기 어렵다
3) 멀티스레드 환경에서 동기화 문제가 발생할 수 있다.
4) 하나의 객체를 완성하기까지 메서드를 여러 번 호출해야 한다.
장점
1) 객체의 불변성을 보장한다. (setter 메소드가 없으므로)
2) build() 함수가 잘못된 값이 입력되었는지 검증하게 할 수도 있다.
3) 한 번에 객체를 생성하므로 객체 일관성이 깨지지 않는다.
단점
1) 객체를 생성하기 위해 빌더 객체를 추가로 생성해야 하므로 오버헤드가 발생하다.
2) 일부 필드의 값을 안넣어도 필드가 Null로 들어가면서 객체가 생성가능하여, 개발자가 필수적으로 설정해야 하는 필드를 빠트릴 수 있다.
예를 들어 , 위의 예시에서 userPassword와 money에 대한 값을 넣지 않아도 생성가능하다.
User user = User.builder()
.userId("유저1")
.email("email1")
.build();
userRepository.save(user);