

Creator (생성자 역할)
팩토리 메서드 (createProduct)
Product (제품 인터페이스)
Concrete Creator (구체 생성자)
Concrete Product (구체 제품)
Client (사용자)
클라이언트는 Creator가 제공하는 팩토리 메서드를 호출한다.Creator는 내부적으로 어떤 Product를 생성할지 구체 Creator에게 위임한다.Creator는 팩토리 메서드를 구현(override)하여 특정 Concrete Product를 반환한다.클라이언트는 반환된 Product 인터페이스를 통해 객체를 다루며, 내부에서 어떤 클래스가 생성되었는지는 알 필요가 없다.Creator/ConcreteProduct만 수정하면 된다.
// Product 인터페이스
interface Button {
render(): void;
}
// Concrete Product
class HTMLButton implements Button {
render() {
console.log("Render HTML Button");
}
}
class WindowsButton implements Button {
render() {
console.log("Render Windows Button");
}
}
// Creator (팩토리 메서드 보유)
abstract class Dialog {
abstract createButton(): Button;
renderDialog() {
const btn = this.createButton();
btn.render();
}
}
// Concrete Creator
class WebDialog extends Dialog {
createButton(): Button {
return new HTMLButton();
}
}
class WindowsDialog extends Dialog {
createButton(): Button {
return new WindowsButton();
}
}
// 사용 예시
let dialog: Dialog;
dialog = new WebDialog();
dialog.renderDialog(); // Render HTML Button
dialog = new WindowsDialog();
dialog.renderDialog(); // Render Windows Button
개방-폐쇄 원칙(OCP)을 잘 보여주는 예시다.const createUser = (name, age) => ({
name,
age,
greet() {
console.log(`Hi, I'm ${this.name}, ${this.age} years old.`);
},
});
const user = createUser("Hanbyeol", 30);
user.greet(); // Hi, I'm Hanbyeol, 30 years old.
생성자 함수와의 차이
User(name, age) { this.name = name; this.age = age; } 처럼 new 키워드를 써야 하는 생성자 함수와 달리, 팩토리 함수는 단순히 객체를 반환한다.new를 실수로 빼먹는 문제나, this 바인딩 관련 오류에서 자유롭다.캡슐화와 은닉
클로저를 이용하면 private 변수를 만들 수도 있다. 이는 ES6 클래스가 도입되기 전, 자바스크립트에서 은닉을 구현하는 대표적인 방식이었다.const createCounter = () => {
let count = 0; // private
return {
increment: () => ++count,
get: () => count,
};
};
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.get()); // 1
console.log(counter.count); // undefined (외부 노출 안 됨)
정리
new에 의존하지 않으며, 클로저를 통한 은닉 같은 부가 효과도 제공할 수 있다.