Javascript Pattern

추상 팩토리 패턴

Javascript 의 디자인 패턴 중 하나로서, 말 그대로 객체를 추상화 하여 공장처럼 찍어내는 패턴이라는 의미이다. ECMA 5 이후 부터는 Class에 대한 개념이 생겨 Java와 비슷하게 사용할 수 있지만, 여기에서 설명하는 추상 팩토리 패턴은 prototype을 기준으로 설명한다.

추상 팩토리 패턴을 보며 가장 많이 나오는 예제가 왕과 왕국에 대한 예제가 많이 나온다. 이 글에서는 좀 더 쉽게 설명하기 위해 통장 입/출금을 예시로 든다. 일단 계좌에 대한 기능으로는 기본적으로 사용해야할 입금과 출금 의 기능이 있을 것이다. 그리고 그 기능을 각 은행 별로 해당 기능을 공유할 것이다. 먼저 계좌에 대한 기능을 구현해보겠다.

1
2
3
4
5
6
7
8
9
10
11
var AccountFactory = ( function() {
var personalAccount = null;
return {
deposit: function() {

},
withdraw: function() {

}
}
})();

빌더 패턴

Wiki 백과에 따르면 빌더 패턴이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다 라고 정의하고 있다. 빌더 패턴은 생성자 인자로 너무 많은 인자가 넘겨지는 경우, 그 인자가 어떤 값인지 파악하기 힘들어, 그에 따라 매개 변수를 받아 한번에 처리할 수 있도록 하기 위해 고안해낸 패턴이라고 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Typescript
class SetCharacter{
private userId: string;
private level: number;
private gender: string;

constructor(userId: string, level: number, gender: string) {
this.userId = userId;
this.level = level;
this.gender = gender;
}

getUserId(): string {
return this.userId;
}
getLevel(): number {
return this.level;
}
getGender(): string {
return this.gender;
}
}

let martin = new SetCharacter('martin', 30, 'man');

// Javascript
var SetCharacter = (function () {
function SetCharacter(userId, level, gender) {
this.userId = userId;
this.level = level;
this.gender = gender;
}
SetCharacter.prototype.getUserId = function () {
return this.userId;
};
SetCharacter.prototype.getLevel = function () {
return this.level;
};
SetCharacter.prototype.getGender = function () {
return this.gender;
};
return SetCharacter;
}());

var martin = new SetCharacter('martin', 30, 'man');

위의 Class의 경우에는 케릭터를 생성하는 함수가 있다. 그 함수에는 인자로 해서 ‘이름, 나이, 성별’ 을 차례대로 집어넣게 되어있는데, 만약 특정 데이터가 없거나 혹은 개발자의 실수로 인자의 순서를 잘 못 넣은 경우의 사이드 이펙트는 걷잡을 수 없을 것이다. 이러한 단점을 보완할 수 있는 것이 빌더 패턴이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class Character {
private userName: string;
private gender: number;
private phoneNumber: string;

private userId: string;
private job: string;
private grade: string;

constructor (builder) {
this.userName = builder.userName;
this.gender = builder.gender;
this.phoneNumber = builder.phoneNumber;

this.userId = builder.userId;
this.job = builder.job;
this.grade = builder.grade;
}

static createCharacter(userName, gender, phoneNumber ) {
return new CharacterBuilder(userName, gender, phoneNumber);
}
}

class CharacterBuilder {
private userName: string;
private gender: string;
private phoneNumber: number;

private userId: string;
private job: string;
private grade: string;

constructor (userName, gender, phoneNumber) {
this.userName = userName;
this.gender = gender;
this.phoneNumber = phoneNumber;
}

setUserId(userId): object {
this.userId = userId;
return this;
}

setGrade(grade): object {
this.grade = grade;
return this;
}

setJob(job): object {
this.job = job;
return this;
}

build() {
return new Character(this);
}
}

var createCharacter = Character.createCharacter('김영훈', '01012345678', 'man');
var martin = createCharacter.setUserId('martin').build();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var Character = (function () {
function Character(builder) {
this.userName = builder.userName;
this.gender = builder.gender;
this.phoneNumber = builder.phoneNumber;
this.userId = builder.userId;
this.job = builder.job;
this.grade = builder.grade;
}
Character.createCharacter = function (userName, gender, phoneNumber) {
return new CharacterBuilder(userName, gender, phoneNumber);
};
return Character;
}());
var CharacterBuilder = (function () {
function CharacterBuilder(userName, gender, phoneNumber) {
this.userName = userName;
this.gender = gender;
this.phoneNumber = phoneNumber;
}
CharacterBuilder.prototype.setUserId = function (userId) {
this.userId = userId;
return this;
};
CharacterBuilder.prototype.setGrade = function (grade) {
this.grade = grade;
return this;
};
CharacterBuilder.prototype.setJob = function (job) {
this.job = job;
return this;
};
CharacterBuilder.prototype.build = function () {
return new Character(this);
};
return CharacterBuilder;
}());
var createCharacter = Character.createCharacter('김영훈', '01012345678', 'man');
var martin = createCharacter.setUserId('martin').build();

팩토리 메소드

단일체

프로토타입


출처

http://asfirstalways.tistory.com/350
http://using.tistory.com/71
http://leetaehoon.tistory.com/57
http://jays1204.github.io/pattern/2015/11/09/builder-pattern.html
http://jdm.kr/blog/217
https://www.zerocho.com/category/JavaScript/post/57bab0ee5abe0c17006fe22f

현재 이커머스회사에서 frontend 개발자로 업무를 진행하고 있는 Martin 입니다. 글을 읽으시고 궁금한 점은 댓글 혹은 메일(hoons0131@gmail.com)로 연락해주시면 빠른 회신 드리도록 하겠습니다. 이 외에도 네트워킹에 대해서는 언제나 환영입니다.:Martin(https://github.com/martinYounghoonKim
초보자의 Docker 사용기
단위 테스트 삽질기