객체를 만들기 위한 인터페이스를 정의하나, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 하위 클래스가 정하도록 하는 패턴. 즉, 객체 생성 처리를 서브클래스로 분리 해 처리하도록 캡슐화 하는 패턴.
참고 - https://defacto-standard.tistory.com/113DIP (Dependency Inversion Principle, 의존 관계 역전의 원칙) 란?
객체 지향 설계의 5대 원칙(SOLID) 중 하나로써,
의존 관계를 맺을 때, 변화하기 쉬운것 보단 변화하기 어려운 것에 의존해야 한다는 원칙.
변화하기 어려운 것 - 정책, 전력과 같은 어떤 큰 흐름이나 개념처럼 추상적인 것.
변화하기 쉬운 것 - 구체적인 방식, 사물 등과 같은 것.
으로 생각하면 이해하기 조금 더 수월하다.
구현 예제는 스타크래프트의 팩토리에서 유닛을 뽑기 위해 필요한 자원 객체를 Factory Method를 이용해 만든 예제 입니다.
Typescript로 abstract class(추상 클래스)와 abstract method(추상 메서드)를 이용해서 구현했습니다.
// Creator - 기본적인 FactoryMethod를 구현하고, ConcreteProduct를 반환한다.
abstract class Factory {
// Product 타입의 객체를 반환하는 FactoryMethod를 선언한다.
public abstract createUnit(): Unit;
// Product 객체 생성을 위해 FactoryMethod를 호출한다.
public getUnit(): Unit {
return this.createUnit();
}
}
// ConcreteCreator - FactoryMethod를 재정의 하여 ConcreteProduct 인스턴스를 반환한다.
// 추상 클래스를 상속하는 클래스에선 추상 메서드를 꼭 구현해야 한다.
class CreateSiegeTank extends Factory {
public createUnit(): Unit {
console.log('SiegeTank를 만들었습니다.');
return new SiegeTank();
}
}
class CreateGoliath extends Factory {
public createUnit(): Unit {
console.log('Goliath을 만들었습니다.');
return new Goliath();
}
}
// Product - FactoryMethod가 생성하는 객체의 인터페이스를 정의한다.
interface Unit {
mineral: number;
gas: number;
food: number;
}
// ConcreteProduct - Product에 정의된 인터페이스를 실제로 구현한다.
class SiegeTank implements Unit {
mineral: number = 0;
gas: number = 0;
food: number = 0;
constructor() {
this.mineral = 150;
this.gas = 100;
this.food = 2;
}
}
class Goliath implements Unit {
mineral: number = 0;
gas: number = 0;
food: number = 0;
constructor() {
this.mineral = 100;
this.gas = 50;
this.food = 2;
}
}
// Client Code
function callUnit(factory: Factory): void {
const unitInfo = factory.getUnit();
console.log(`
미네랄 : ${unitInfo.mineral}
가스 : ${unitInfo.gas}
인구수 : ${unitInfo.food}
를 소모 하였습니다.
`);
}
callUnit(new CreateSiegeTank());
callUnit(new CreateGoliath());
// 결과
// SiegeTank를 만들었습니다.
// 미네랄 : 150
// 가스 : 100
// 인구수 : 2
// 를 소모 하였습니다.
// Goliath을 만들었습니다.
// 미네랄 : 100
// 가스 : 50
// 인구수 : 2
// 를 소모 하였습니다.