빌더
"유창한 인터페이스를 제공, 복잡한 객체의 생성을 단순화"
단계별로 객체를 만들 수 있음 => 가독성, 일반적인 개발자 사용성 향상
가장 좋은 상황 : 인자의 목록이 길거나, 많은 복잡한 매개 변수를 입력해서 사용하는 생성자가 있는 클래스
class Boat {
constructor (
hasMotor, motorCount, mototBrand, motorModel,
hasSails, sailsCount, sailsMaterial, sailsColor,
...
)
}
const myBoat = new Boat(ture, 2, 'Best Motor Co.', 'OM123', true, 1, 'fabric', 'white', 'blue', false);
어쩔거야 이거, 맨날 칠거니?
오류가 발생하기 쉽고, 인수를 알아보기 어려움
1단계 해결방법 : 모든 인자를 하나의 객체 리터럴에 모음
class Boat {
constructor (allParameters) {
// ...
}
}
const myBoat = new Boat({
hasMotor : true,
motorCount : 2,
mototBrand : 'Best Motor Co. ',
motorModel : 'OM123',
// ...
})
매개 변수값이 무엇인지 명확하게 알 수 있음
다만 실제 입력이 무엇인지 알기 위해 클래스 정의 문서, 클래스 코드를 봐야 함
2단계 해결방법 : 일관된 클래스를 생성하도록 강제
Ex) hasMotor : true 이면 [ motorCount, motorBrand, motorModel ] 지정 강제화
빌더 패턴은 작은 결함을 교정하고 읽기 쉬우며 자체 문서화 가능 => 일관된 객체 생성을 위한 지침 제공
class BoatBuilder {
withMotors (count ,brand, model) {
this.hasMotor = true;
this.motorCount = count;
this.motorBrand = brand;
this.motorModel = model;
return this;
}
withSails (count, material, color) {
this.hasSails = true;
this.sailsColor = count;
this.sailsMaterial = material;
this.sailsColor = color;
return this;
}
hullcolor (color) {
this.hullcolor = color;
return this;
}
withCabin () {
this.hasCabin = true;
return this;
}
build () {
return new Boat({
hasMotor : this.hasMotor,
motorCount : this.motorCount,
motorBrand : this.motorBrand,
motorModel : this.motorModel,
hasSails : this.hasSails,
sailsCount : this.sailsCount,
sailsMaterial : this.sailsMaterial,
sailsColor : this.sailsColor,
hullcolor : this.hullcolor,
hasCabin : this.hasCabin,
})
}
}
// 사용 예시
const myBoat = new BoatBuilder()
.withMotors(2, 'Best Motor Co.' , 'OM123')
.withSails(1, 'fabric', 'white')
.withCabin()
.hullcolor('blue')
.build();
BoatBuilder 클래스의 역할은 일부 헬퍼 함수를 사용하여 Boat 생성에 필요한 모든 매게변수를 모음
빌더 패턴 구현하기 위한 일반적인 규칙
- 주요 목적은 복잡한 생성자를 더 읽기 쉽고 관리가 쉬운 여러가지 단계로 나눔
- 한번에 관련된 여러 매개변수들을 설정할 수 있는 빌더 함수를 만듦
- Setter 함수를 통해 입력받을 값이 무엇인지 명확히 하고, 빌더 인터페이스를 사용하는 사용자가 알 필요가 없는 파라미터를 세팅하는 더 많은 로직을 setter함수 내에 캡슐화
- 필요 시 형 변환, 정규화, 유효성 검사와 같은 조작을 추가, 빌더 클래스를 사용할때 수행 해야 하는 작업을 단순화
함수를 호출 할 때도 적용 할 수 있음
1. URL 객체 빌더 구현
* 실제로 쓰기위해서는 내장 URL 클래스 사용 권장
export class Url {
constructor (protocol, username, password, hostname, port, pathname, search, hash) {
this.protocol = protocol;
this.username = username;
// ... 귀찮아요
this.hash = hash;
this.validate();
}
validate() {
if (!this.protocol || !this.hostname) {
throw new Error("Must specify at least a " + "protocol and hostname");
}
}
toString () {
let url = '';
url += `${this.protocol}://`
if (this.username && this.password) {
url += `${this.username}:${this.password}`
}
url += this.hostname;
if (this.port) {
url += this.port;
}
if (this.pathname) {
url += this.pathname;
}
if (this.search) {
url += this.search;
}
if (this.hash) url += this.hash;
return url;
}
}
모든 구성요소를 가져오려면 URL 클래스의 생성자가 필연적으로 커짐
또한 매개변수의 값이 어떤 값인지 인지하고 있어야 함
return new Url('https' , null, null, 'example.copm', null, null, null, null);
여기에 빌더 패턴을 적용하기에 최적의 상황
Setter 함수가 있는 Url Builer 클래스를 만들어봅시다.
// urlBuilder.js
export class urlBuilder {
setProtocol (protocol) {
this.protocol = protocol;
return this;
}
setAuthentication (username, password) {
this.username = username;
this.password = password;
return this;
}
setHostname (hostname) {
this.hostname = hostname;
return this;
}
setPort (port) {
this.port = port;
return this;
}
setPathname (pathname) {
this.pathname = pathname;
return this;
}
setSearch (search) {
this.search = search;
return this;
}
setHash (hash) {
this.hash = hash;
return this;
}
build () {
return new Url(this.protocol, this.username, this.password,
this.hostname, this.port , this.pathname, this.search, this.hash)
}
}
어때요? 매우 직관적이고 참 쉽죠?
Url 에 인증정보를 지정하려는 경우 [사용자 이름, 비밀번호]가 모두 필요함을 명확히 함
실제 사용을 해봅시다.
// index.js
import { UrlBuilder } from './';
const url = new UrlBuilder()
.setProtocol('https')
.setAuthentication('user', 'pass')
.setHostname('example.com')
.build();
console.log(url.toString());
가독성 개점
각 setter 함수는 설정하는 매개 변수에 대한 힌트 제공, 클린코드에 도움이 될듯
Summary
빌더 패턴 : 복잡한 객체를 생성하거나 복잡한 함수를 호출하는 문제의 해결책
Ex) http 내장된 requests() API, HTTP 클라이언트 요청 생성
superagent
.post('https://example.com/api/person')
.send({name : 'John Doe' ,role : 'user'})
.set('accept', 'json')
.then((response) => {
// 처리
})
new 연산자 없음
요청을 실행시키는것은 then() 함수
superagent 객체가 프라미스가 아니라 then() 함수가 빌더객체를 통해 만들어진 요청을 실행하게 하는 thenable 이라는 것
'Javascript > Node.js' 카테고리의 다른 글
Wiring Pattern - 생성자 디자인 패턴 (0) | 2022.02.03 |
---|---|
Singleton Pattern - 생성자 디자인 패턴 (0) | 2022.02.03 |
Domenic Revealing Constructor Pattern - 생성자 디자인 패턴 (0) | 2022.02.03 |
Factory Pattern - 생성자 디자인 패턴 (0) | 2022.02.03 |
디자인 패턴 (0) | 2022.02.03 |
댓글