1. 의도
•
GoF
◦
객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브클래스가 내리도록 합니다.
◦
객체 생성을 캡슐화
•
Head First
◦
객체를 생성할때 필요한 인터페이스를 만듬
◦
어떤 클래스의 인스턴스를 만들지는 서브 클래스에서 결정
◦
사용하는 서브클래스에 따라 생산되는 객체 인스턴스가 결정됨
2. 활용성
•
GoF
◦
어떤 클래스가 자신이 생성 해야하는 객체의 클래스를 예측할 수 없을 때
◦
생성할 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때
◦
객체의 생성의 책임을 몇 개의 보조 서브클래스 가운데 하나에게 위임하고, 어떤 서브클래스가 위임자인지에 대한 정보를 국소화 하고 싶을 때
3. 구조
•
UML Class Diagram
4. 참여자
참여자 | 역할 | 예시 |
Product | 팩토리 메서드가 생성하는 객체의 인터페이스 | 피자 |
ConcreteProduct | Product 클래스에 정의딘 인터페이스를 실제로 구현 | 뉴욕치즈피자, 뉴욕페퍼로니피자
시카고치즈피자, 시카고페퍼로니피자 |
Creator (Factory) | Product 타입의 객체를 반환하는 팩토리 메서드 선언
- 팩토리 메서드를 기본적으로 구현 (ConcreteProduct 객체 반환)
- Product 객체 생성을 위해 팩토리 메서드 호출 | 피자 가게 (createPizza) |
ConcreteCreator
(ConcreteFactory) | 팩토리 메서드를 재정의하여 ConcreteProduct 인스턴스 반환 | 뉴욕 피자 가게 (createPizza)
시카고 피자 가게 (createPizza) |
5. 협력 방법
•
Creator는 자신의 서브클래스를 통해 실제 필요한 팩토리 메서드를 정의하여 적절한 concreteProduct의 인스턴스를 반환할 수 있게 함
6. 결과
•
응용프로그램에 국한된 클래스가 실제 코드에 종속되지 않게 해줌
◦
Product 클래스에 정의된 인터페이스와만 동작하도록 구현
•
서브클래스에 대한 훅(hook) 메서드 제공
•
병렬적인 클래스 계통을 연결하는 역할 담당
•
단점
◦
사용자가 concreteProduct 객체 하나만 만들려 할때도 Creator 클래스를 서브클래싱해야 할지도 모름
7. 예시 코드
const nyPizzaStore = new NYPizzaStore();
const chicagoPizzaStore = new ChicagoPizzaStore();
const nyCheesePizza = nyPizzaStore.createPizza('cheese');
const nyVeggiePizza = nyPizzaStore.createPizza('veggie');
const chicagoCheesePizza = chicagoPizzaStore.createPizza('cheese');
const chicagoVeggiePizza = chicagoPizzaStore.createPizza('veggie');
for (const pizza of [
nyCheesePizza,
nyVeggiePizza,
chicagoCheesePizza,
chicagoVeggiePizza,
]) {
console.log(pizza?.get());
}
TypeScript
복사
// Product
interface IPizza {
get(): string;
}
class NYCheesePizza implements IPizza {
get(): string {
return 'NYCheesePizza';
}
}
class NYVeggiePizza implements IPizza {
get(): string {
return 'NYVeggiePizza';
}
}
class ChicagoCheesePizza implements IPizza {
get(): string {
return 'ChicagoCheesePizza';
}
}
class ChicagoVeggiePizza implements IPizza {
get(): string {
return 'ChicagoVeggiePizza';
}
}
TypeScript
복사
// Creator
interface IPizzaStore {
createPizza(type: string): IPizza | null;
}
class NYPizzaStore implements IPizzaStore {
createPizza(type: string): IPizza | null {
if (type === 'cheese') {
return new NYCheesePizza();
} else if (type === ' veggie') {
return new NYVeggiePizza();
}
return null;
}
}
class ChicagoPizzaStore implements IPizzaStore {
createPizza(type: string): IPizza | null {
if (type === 'cheese') {
return new ChicagoCheesePizza();
} else if (type === ' veggie') {
return new ChicagoVeggiePizza();
}
return null;
}
}
TypeScript
복사
8. 팩토리 패턴과 추상 팩토리 비교
•
추상 팩토리
◦
연관된 객체를 모아두는 것에 집중
◦
클라이언트에서 서로 연관된 일련의 제품을 만들어야할 때
◦
즉 제품군을 만들어야할 때
•
팩토리 메서드
◦
어떤 객체를 생성할지에 집중
◦
클라이언트 코드와 인스턴스를 만들어야할 구상 클래스를 분리해야 할때
◦
어떤 구상 클래스가 필요할지 미리 알 수 없을 때 유용
▪
서브 클래스 만들고 팩토리 메서드를 구현