Design Pattern

팩토리 메서드 패턴 Factory Method Pattern

La.place 2019. 4. 18. 23:25

 

 지난 포스트에서 다뤘던 추상 팩토리 패턴(Abstract Factory Pattern)에 이어, 이번엔 팩토리 메서드 패턴(Factory Method Pattern)에 대해 정리해 보도록 하자. 이전 포스트의 "마지막에 라떼의 종류가 여러 가지가 된다면 어떻게 하면 좋을까?"라는 질문을 던졌었는데, 이 문제를 해결하기 위해 팩토리 메서드 패턴을 이용하면 좋다. 거두절미하고 예제 코드를 보도록 하자.

class CafeLatte {
    constructor() {
    	this.price = 3000;
    }
    
    getPrice() {
    	return this.price;
    }
}

let latte = new CafeLatte();
latte.getPrice(); // 3000

latte.gerPrice(); 함수는 특정 인스턴스를 받아 가격을 리턴하는 간단한 함수이다. 위 코드는 카페라떼의 인스턴스를 받아 가격을 리턴한다. 라떼의 종류가 하나일 땐 별로 문제가 되지 않는다. 이제 새로운 종류의 라떼를 추가해 보도록 하자. 개인적으로 달콤한 걸 좋아하니 카라멜라떼를 추가해 보도록 하겠다.

class CafeLatte {
    constructor() {
    	this.price = 3000;
    }
    
    getPrice() {
    	return this.price;
    }
}

class CaramelLatte {
    constructor() {
    	this.price = 5000;
    }
    
    getPrice() {
    	return this.price;
    }
}

let latte;
let latteType = 'caramel';

if(latteType === 'cafe') {
    latte = new CafeLatte();
} else if(latteType === 'caramel') {
    latte = new CaramelLatte();
} 

latte.getPrice(); // 5000

새로운 타입인 카라멜 라떼를 추가했다. 이제 라떼의 타입에 따라 다른 가격을 반환해주게 해야 한다. 따라서 분기문을 넣어 타입에 따라 다른 객체를 할당하도록 했다. 더 개선할 부분은 없을까? 타입에 따라 인스턴스가 생성되는데, 이 부분에 타입을 받아서 생성할 수 있도록 팩토리를 만들면 좋지 않을까? 아래 코드를 보도록 하자.

class CafeLatte {
    constructor() {
    	this.price = 3000;
    }
    
    getPrice() {
    	return this.price;
    }
}

class CaramelLatte {
    constructor() {
    	this.price = 5000;
    }
    
    getPrice() {
    	return this.price;
    }
}

class LatteFactory() {
    static create(latteType) {
    	if(latteType === 'cafe') {
            return new CafeLatte();
        } else if(latteType === 'caramel') {
            return new CaramelLatte();
        } 
    }
}

let latte = LatteFactory.create('caramel');
latte.getPrice(); // 5000

 팩토리를 만들어 create() 메서드에 타입을 받아 인스턴스를 생성하도록 하였다. 구체화하는 로직을 묶어 응집도를 높이고, 코드도 더 깔끔해졌다. 여기까지가 팩토리 메서드 패턴에 대한 가장 간단한 예제이다. 사실 이 패턴은 부모 클래스에게 알려지지 않은 구체 클래스를 자식 클래스가 결정하도록 하는 패턴인데, 위 구현은 뭔가가 부족한 느낌이다. 그 이유는 자바스크립트는 태생이 프로토타입 기반이다보니 C++이나 JAVA와 같은 상속 개념이 존재하지 않고, 부분적인 상속 개념만 구현이 가능하다 보니 다른 언어의 팩토리 메서드 패턴과는 차이가 발생할 수밖에 없다. 라떼 팩토리의 create(); 메서드도 이전 포스트에서 구현했던 커피 팩토리와 크게 다르지 않다.

function coffeeFactory(type) {
    let coffee;
    
    if(type === 'latte') coffee = new Latte();
    else if(type === 'espresso') coffee = new Espresso();
    else if(type === 'cappuccino') coffee = new Cappuccino();
    else if(type === 'mocha') coffee = new Mocha();
    
    return coffee;
}

따라서 이전에 공유했던 desgin patterns JS에서도 딱히 팩토리 메서드 패턴을 구현하고 있진 않다. 추상 팩토리도 일부 팩토리 메서드를 차용해서 구현할 수도 있는데, 특히 자바스크립트에서는 경계가 뚜렷하지 않으므로 둘을 구분하는데 큰 의미는 없는 것 같다.

 

딱히(?) 앞 포스트와 큰 차이는 없는 것 같다. 정리하면 두 팩토리 패턴의 핵심을 어떻게 팩토리를 이용하여 인스턴스를 어떻게 잘 생성하는가 정도로 알아두면 좋을 것 같다는 생각이 든다. 마지막으로 JS로 구현하다보니 예제를 만드는데도 약간 한계가 느껴지는데 타입스크립트(TypeScript)로 설명을 했으면 좀 더 쉽고 좋은 에제를 만들 수 있지 않았을까 하는 아쉬움이 남는다.