추상 팩토리: 관련 객체들의 구상 클래스들을 지정하지 않고도 관련 객체들의 모음을 생성할 수 있도록 하는 생성패턴
각 제품군에 해당되는 개별적인 인터페이스를 명시적으로 선언하고, 제품의 모든 변형은 이 인터페이스를 따르게 해야 함
제품 패밀리 내의 모든 개별 제품들의 생성 메서드들이 목록화 되어 있는 인터페이스인 추상 팩토리 패턴 선언
추상 팩토리 인터페이스를 기반으로 각 특성의 제품을 생성하는 별도의 팩토리 클래스 생성
클라이언트 코드는 자신에 해당하는 추상 인터페이스를 통해 제품들 모두와 작동해야 함
프로그램은 초기화 단계에서 구상 팩토리 객체를 생성하고, 환경, 구성 설정에 따라 팩토리 유형을 선택함
// 생성할 모든 객체들을 담은 추상 패토리 인터페이스
interface AbstractFactory {
createProductA(): AbstractProductA;
createProductB(): AbstractProductB;
}
// 구상 팩토리에서 추상 팩토리를 바탕으로 각각의 특성에 맞는 객체 생성
class ConcreteFactory1 implements AbstractFactory {
public createProductA(): AbstractProductA {
return new ConcreteProductA1();
}
public createProductB(): AbstractProductB {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
public createProductA(): AbstractProductA {
return new ConcreteProductA2();
}
public createProductB(): AbstractProductB {
return new ConcreteProductB2();
}
}
// 제품군의 모든 변형 객체를 생성해주는 객체 생성 인터페이스 구현
// 여기서는 A제품을 생성하는 인터페이스
interface AbstractProductA {
usefulFunctionA(): string;
}
// 구체적인 클래스 구현, 각각의 객체는 객체의 특성에 맞추어 구현됨
class ConcreteProductA1 implements AbstractProductA {
public usefulFunctionA(): string {
return 'The result of the product A1.';
}
}
class ConcreteProductA2 implements AbstractProductA {
public usefulFunctionA(): string {
return 'The result of the product A2.';
}
}
//한번더 반복
interface AbstractProductB {
usefulFunctionB(): string;
anotherUsefulFunctionB(collaborator: AbstractProductA): string;
}
// A와 인터페이스, 객체 생성 방법은 동일하나 다른 특성을 갖는 객체 생성
class ConcreteProductB1 implements AbstractProductB {
public usefulFunctionB(): string {
return 'The result of the product B1.';
}
public anotherUsefulFunctionB(collaborator: AbstractProductA): string {
const result = collaborator.usefulFunctionA();
return `The result of the B1 collaborating with the (${result})`;
}
}
class ConcreteProductB2 implements AbstractProductB {
public usefulFunctionB(): string {
return 'The result of the product B2.';
}
public anotherUsefulFunctionB(collaborator: AbstractProductA): string {
const result = collaborator.usefulFunctionA();
return `The result of the B2 collaborating with the (${result})`;
}
}
// 클라이언트들은 추상 인터페이스를 통해 원하는 특성의 객체만를 사용할 수 있게 됨
function clientCode(factory: AbstractFactory) {
const productA = factory.createProductA();
const productB = factory.createProductB();
console.log(productB.usefulFunctionB());
console.log(productB.anotherUsefulFunctionB(productA));
}
/*
Client: Testing client code with the first factory type...
The result of the product B1.
The result of the B1 collaborating with the (The result of the product A1.)
*/
console.log('Client: Testing client code with the first factory type...');
clientCode(new ConcreteFactory1());
console.log('');
/*
Client: Testing the same client code with the second factory type...
The result of the product B2.
The result of the B2 collaborating with the (The result of the product A2.)
*/
console.log('Client: Testing the same client code with the second factory type...');
clientCode(new ConcreteFactory2());
출처:
https://refactoring.guru/ko/design-patterns/abstract-factory