빌더를 사용하는 장점은 무엇인가?
1. setter 방식의 단점
기존의 자주 사용하던 자바빈즈 패턴(= setter
) 의 경우, 객체 하나를 만드려면
여러개의 메서드를 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓이게 된다.
(=객체의 불변성이 깨진 상태)
멀티 스레드 환경에서 안정성을 얻으려면 추가 작업을 해줘야 한다.
예) 여러개의 스레드가 Student라는 객체에 접근했을 때
1번 스레드는 Student에 아무 값이 없는 빈 객체일수도 있고 2번 객체는 이름과 나이가 setter로 설정된
객체일 수도 있다. 하지만 setter를 제거하고 애초에 처음 만들때 값을 가진 객체로 생성하고
그 값이 불변하다면 Thread-safe 하다고 말할 수 있다.
2. 불변 객체
(1) 생성자
그럼 객체를 불변객체로 만드는 방법엔 생성자와 빌더가 있다.
근데 매개변수가 많을 경우, 생성자로 사용하는 방법은 조금 번거로울 수가 있다.
public class NutritionFacts {
private final int servingSize; //필수
private final int servings; //필수
private final int calories; //선택
private final int fat; //선택
private final int sodium; //선택
private final int carbohydrate; //선택
}
이렇게 영양성분에 대한 객체가 있다면 여기서 필수값과 선택값에 맞춰 다양한 생성자가 생성되어야 한다.
그래서 다양한 생성자 중 필요한 생성자를 골라 써야된다는 번거로움이 있다.
게다가 인텔리제이의 경우엔 생성자를 생성할 때 뭐가 들어갈지 이름을 띄워주긴 하지만 타입이 같다면 a 자리에 b의 값을 넣을 수도 있고 컴파일러가 알아채지 못하기 때문에 엉뚱한 값이 나올수도 있다.
(2) 빌더
그래서 다음 방법이 바로 빌더패턴이다. 빌더패턴을 사용해서 setter
처럼 원하는 값을 method chaining
방식으로 쉽고
어떤 필드에 어떤 값이 들어갈지 보기 쉽게 추가할 수 있고 생성자 방식처럼 build
메서드를 통해 새로운 불변 객체를 리턴 받는다.
게다가 lombok
을 사용하면 @Builder
어노테이션 하나로 복잡한 빌더패턴을 쉽게 작성이 가능하기 때문에 더 추천하다.
끝맺음.. 🍀
당시 면접에서는 빌더를 통해 생성자와는 달리 무슨 값에 뭐가 들어가는지 쉽게 알 수 있다(가독성을 높일 수 있다).. 같은..정도의 대답 밖에 못했었는데 불과 두달 전인데도 불구하고 이펙티브 자바를 읽으면서 그때 그 대답이 너무 아쉬웠다..
뭐 지금도 잘 쓴건지 모르겠고 ㅋㅋ 걍 내가 이해한 바 + 이펙티브 자바를 읽고 내용 정리한 거 뿐이지만..
담에 면접땐 더 잘 대답하길 바라며..
그리고 사실 롬복을 쓰면서 @Builder
를 써서 그냥 쓰기만 했지, 내부 소스코드가 어떻게 이뤄진지 알지 못했는데 (궁금하지도 않았었음 ㅎ) 이번 기회에 아 그래서 build를 마지막에 붙였구나~ 왜 Builder.xxx.build()
이런 구조가 되는구나 알게되었다.
이펙티브 자바를 읽으면서 찬찬히 다른 것도 정리해봐야겠다...