추상 팩토리, Kit 이라고도 불린다.
가구 상점 시뮬레이터를 만들고 있다고 가정했을 때, 코드는 아래를 나타내는 클래스를 구성하고 있어야 한다.
- 연관된 상품군 (소파, 의자, 커피 테이블)
개별 상품을 만들 수 있고, 다른 오브젝트와 매치시켜 같은 상품 회사의 연관된 상품을 만들어낼 수 있어야 한다.
ex. IKEA 의자를 산 손님은 추가 주문 시 IKEA 소파를 사고 싶어 한다.
또한, 새로운 상품이나, 회사를 추가하더라도 이미 존재하는 코드들을 수정하고 싶지 않다. 가구 상인은 그들의 카탈로그를 자주 업데이트하기 때문에, 그때마다 코드를 수정하고 싶지는 않다.
명시적으로 각자 상품군의 인터페이스를 선언한다. 그러면 다양한 종류의 상품을 만들어낼 수 있다.
그 다음은 생성 메소드들(createChair
, createSofa
, createCoffeeTable
)을 가진 상품 회사 Abstract Factory
를 선언하는 것이다. 이 함수들은 반드시 이전에 우리가 추출했던 인터페이스에 의해 표현된 추상 상품 타입들을 반환해야 한다. (createChar(): Chair
, createSofa(): Sofa
)
이제 각 상품 회사의 상품들의 factory class를 AbstractFactory
인터페이스를 기반으로 만들어낼 수 있다. 하나의 팩토리는 특정 종류의 상품을 리턴하는 클래스이다. 예를 들어서 IKEAFactory는 IKeaChair를 만들 수 있다.
AbstractFactory
: 개념적 제품에 대한 객체를 생성하는 연산, 인터페이스를 정의함ConcreteFactory
: 구체적인 제품에 대한 객체를 생성하는 연산을 구현함AbstractProduct
: 개념적 제품 객체에 대한 인터페이스를 정의함ConcreteProduct
: 구체적으로 팩토리가 생성할 객체를 정의한다. AbstractProduct
가 정의하는 인터페이스를 구현한다.Client
: AbstractFactory
와 AbstractProduct
클래스에 선언된 인터페이스를 사용한다.ConcreteFactory
클래스의 인스턴스 한 개가 런타임에 만들어진다. 이 구체 팩토리는 어떤 특정 구현을 갖는 제품 객체를 생성한다. 서로 다른 제품 객체를 생성하려면 사용자는 서로 다른 구체 팩토리를 사용해야 한다.AbstractFactory
는 필요한 제품 객체를 생성하는 책임을 ConcreteFactory
서브 클래스에 위임한다.interface AbstractFactory {
createChair(): AbstractChair;
createSofa(): AbstractSofa;
}
interface AbstractSofa {
sitOn(): string;
rest(): string;
legOn(collaborator: AbstractChair): string;
}
interface AbstractChair {
sitOn(): string;
putLeg(): string;
}
class IkeaFactory implements AbstractFactory {
public createChair(): AbstractChair {
return new ConcreteIkeaChair();
}
public createSofa(): AbstractSofa {
return new ConcreteIkeaSofa();
}
}
class EMartFactory implements AbstractFactory {
public createChair(): AbstractChair {
return new ConcreteEmartChair();
}
public createSofa(): AbstractSofa {
return new ConcreteEmartSofa();
}
}
class ConcreteIkeaChair implements AbstractChair {
sitOn(): string {
return `sit on Ikea chair`;
}
putLeg(): string {
return `put your leg on Ikea chair`;
}
}
class ConcreteIkeaSofa implements AbstractSofa {
sitOn(): string {
return "sit on Ikea sofa";
}
rest(): string {
return "rest on Ikea sofa";
}
legOn(collaborator: AbstractChair): string {
return `with Ikea Sofa, leg on chair: ${collaborator.putLeg()}`;
}
}
class ConcreteEmartChair implements AbstractChair {
sitOn(): string {
return `sit on Emart chair`;
}
putLeg(): string {
return `put your leg on Emart chair`;
}
}
class ConcreteEmartSofa implements AbstractSofa {
sitOn(): string {
return "sit on Emart sofa";
}
rest(): string {
return "rest on Emart sofa";
}
legOn(collaborator: AbstractChair): string {
return `with Emart Sofa, leg on chair: ${collaborator.putLeg()}`;
}
}
const clientCode = (factory: AbstractFactory) => {
const chair = factory.createChair();
const sofa = factory.createSofa();
console.log(sofa.rest());
console.log(sofa.legOn(chair));
};
clientCode(new IkeaFactory());
clientCode(new EMartFactory());
rest on Ikea sofa
with Ikea Sofa, leg on chair: put your leg on Ikea chair
rest on Emart sofa
with Emart Sofa, leg on chair: put your leg on Emart chair