Search
♻️

[디자인 패턴 - 생성 패턴] 팩토리 메서드 패턴 (Factory Method)

Tags
Design Pattern
Architcture
Study
Last edited time
2023/06/13 14:49
2 more properties

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. 팩토리 패턴과 추상 팩토리 비교

추상 팩토리
연관된 객체를 모아두는 것에 집중
클라이언트에서 서로 연관된 일련의 제품을 만들어야할 때
즉 제품군을 만들어야할 때
팩토리 메서드
어떤 객체를 생성할지에 집중
클라이언트 코드와 인스턴스를 만들어야할 구상 클래스를 분리해야 할때
어떤 구상 클래스가 필요할지 미리 알 수 없을 때 유용
서브 클래스 만들고 팩토리 메서드를 구현