이번 시간에는 빌더 패턴에 대해서 알아보겠습니다. 이전에 언급한 객체의 완전한 상태, 메서드 체이닝, setter 관련 글을 보고 오시면 더 좋습니다. 그리고 HashMap이나 CharsetDecorder에서는 왜 빌더 패턴이 안 보이나도 같이 고민해 보면 좋을 듯 싶습니다. 생성자에 인자가 많은 것이 있음에도.
먼저, Model에서 x와 y가 필수 필드라고 해 보겠습니다. 그러면, 우리는 아래와 같은 생성자를 생각해 볼 수 있습니다.
아예 생성자에서 x와 y를 받게끔 해 버리면 그만입니다.
간단합니다. 그러면, p가 x만 있거나 y만 값이 있거나, 혹은 둘 다 값이 없는 불완전한 상태에서는 벗어날 수 있습니다.
사실, x와 y만 있는 경우에는 그냥 이렇게 생성자만 둬도 무난할 겁니다. 굳이 아래와 같이 내부 클래스인 ModelBuilder를 둬서 내부 클래스를 만들 필요는 없어 보입니다. 문제는, 속성 값이 매우 많은 경우입니다. x와 y값이 필수 속성 값이고 자잘한 옵션 필드들이 5개 정도 있다고 해 보겠습니다. 어느 인코딩 형식으로 byte 배열이 어느 인코딩으로 인코딩 되었는지 받는 charset 같은 것들이 옵션 필드에 속하는 예입니다.
이 옵션 필드는, 객체가 만들어 지고 나서 설정해도 됩니다. 그런 경우에는 setOption 등으로 열어놓을 수 있을 겁니다.
그리고, 이런 모델을 하나 만든 다음에, 옵션을 나중에 설정할 수 있습니다. 이것은 new Model(2, 3, option)을 한 것과 크게 차이가 없어 보입니다. 그런데, 이것은 모델에 option이 붙여져서 만들어지는 경우를 표현하지 못합니다. 저 코드는 단지, 기본 옵션인 x와 y만 값이 셋팅된 상태에서 출고되었고, 나중에 옵션이 추가된 것을 표현한 것일 뿐입니다.
이 상황을 그림으로 나타내면 위와 같습니다. 객체가 만들어 질 때, option이 들어가지 않은 상태로 만들어 졌습니다. 즉, 옵션까지 들어간 상태로 만들어지길 원한다면 아래와 같은 코드를 Model class에 추가해야 합니다.
x와 y, option을 받는 것이 하나 추가되었습니다. 코드를 줄이려면 아래와 같이 작성하면 될 겁니다.
그런데, 이렇게 하면 상당히 복잡해 집니다. 당장 옵션이 5개가 있는 상황이라면 어떤가요? 생성자가 얼마나 더 필요한가요? 8개? 9개? 아니면 그 이상이 더 필요한가요?
생성자에 들어가는 인수가 적다면, 헷갈릴 여지가 덜 할 겁니다. 그런데, 그 갯수가 많다면 혼동될 여지도 다분합니다. 그러면, 생성자 대신에 setter에 this를 리턴하게 함으로서, method chaining을 하면 될 겁니다. 그러면, 가독성은 나아질 겁니다. 문제는, 이 때 세터는, '이미 만들어진 객체'에 일부 속성만 바꿔줄게의 느낌이 강합니다. 속성이 setting이 된 상태에서 '생성'되는 것과 다릅니다. 옵션이 여러 개가 있고, 이들이 어떤 경우에는 설정이 된 상태에서 만들어지고, 어떤 경우에는 그렇지 않게 하게도 해야 한다면 어떻게 해야 할까요?
이 때 빌더 패턴을 고려해 볼 수 있습니다. 이펙티브 자바 3판에서는 Enum을 이용한 예제도 같이 있습니다만, 저는 그냥 x, y, option만 고려해 보도록 하겠습니다.
필수 필드는 x, y이고, 옵션 필드는 option입니다. 그러므로 x와 y를 인자로 받아서, ModelBuilder에서 x와 y 값을 채우게끔 만듭니다. option은 바깥에서 상황에 따라 set을 할 수도 있고, 그렇지 않을 수도 있습니다. 다음에, aModel에서 새롭게 생성한 모델 빌더를 리턴하는 것을 보시면 됩니다.
만약에 set을 한다면, withOption을 부르면 됩니다. 여기서 return this를 합니다. 즉, 자기 자신을 리턴해 버립니다. 다음에, 인자들을 다 채웠다면, build 메소드에서, 새로운 Model 객체를 생성하고, 새롭게 생성된 객체를 리턴합니다. 이제 Model 클래스를 봅시다.
이제, 3개의 필드는 요래 채우면 됩니다. 빌더에서 setting을 했던 option, x, y 값을 넣어주면 됩니다.
Main에서 Model을 생성할 때에는 아래와 같이 부를 수 있습니다. 이 코드는, x는 4, y 값은 4로 셋팅해 주고, 옵션은 5로 해 주세요. 라는 주문사항을 Builder에게 날리고, 그것이 Model 객체를 만들었다는 생각을 하시면 됩니다. 가독성도 잡으면서, 생성자의 불완전한 상태에 대한 문제점도 잡았음을 볼 수 있습니다.
'디자인패턴' 카테고리의 다른 글
의존성 주입을 왜 쓰는지 간단한 예제로 알아봅시다. (1) | 2021.08.12 |
---|---|
overloading : 잘 쓰면 좋지만 잘못 쓰면 헷갈리기 쉽다. (2) | 2021.01.15 |
setter 를 언제 쓰지 말아야 할 지에 대한 간단한 생각 (2) | 2020.12.18 |
메서드 체이닝 : 여러 속성들을 셋팅할 때 자주 쓴다. (2) | 2020.12.12 |
java 생성자와 객체의 완전한 상태 (2) | 2020.11.27 |
최근댓글