[Javascript] Javascript의 생성 패턴

추상 팩토리 패턴

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

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

var AccountFactory = ( function() {
  var personalAccount = null;
  return {
    deposit: function() {
      
    },
    withdraw: function() {

    }
  }
})();

빌더 패턴

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

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

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();
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

Comments