[Design Pattern with TypeScript] #1 Factory Method

mechaniccoder·2021년 4월 12일
0

Design Pattern

목록 보기
3/3

Why Factory Method?


팩토리 메서드의 유스케이스에 대해서는 아직은 정확하게는 잘 모르겠습니다. 아직은 디자인 패턴을 실제 실무 코드에 어떻게 활용하고, 프런트엔드 프레임워크에서 컴포넌트를 개발할때 이 디자인 패턴을 어떻게 활용하는지 모르겠습니다.

이후에 더 정확한 유스케이스에 대해서 알게 되면 포스트를 다시 정리하는 것으로 하고 오늘은 팩토리 메서드의 원리에 대해 알아보죠.

Diagram


다이어그램을 보면 추상화된 RocketFactory와 Rocket이 있고 이를 상속하는 FastFactoryRocketFactory, FastRocket 클래스가 있습니다. 즉, 로켓을 어떻게 만드는지와 로켓은 어떤 부품을 가지고 있는지 일반적인 것들은 추상클래스에 정의를 하고 이를 활용해 구체적인 팩토리와, 로켓을 생산합니다.

팩토리의 서브클래스는 팩토리 메서드를 제품에 맞게 변경할 수도 있으므로 상황에 유연하게 대처할 수 있겠죠?

Implementation


그럼 typescript를 활용해 직접 구현해보죠.

먼저, 추상화한 팩토리와 로켓을 만들어보겠습니다.

export class RocketFactory {
  public buildRocket(): Rocket {
    const rocket = new Rocket();
    const payload = this.createPayload();
    const stage = this.createStages();
    rocket.payload = payload;
    rocket.stage = stage;
    return rocket;
  }

  createPayload(): Payload {
    return new Payload(0);
  }

  createStages(): Stage[] {
    const engine = new Engine(1000);
    const stage = new Stage([engine]);
    return [stage];
  }
}

export class Rocket {
  payload: Payload;
  stage: Stage[];
}

export class Payload {
  weight: number;
  constructor(weight: number) {
    this.weight = weight;
  }
}

export class Stage {
  engines: Engine[];
  constructor(engines: Engine[]) {
    this.engines = engines;
  }
}

export class Engine {
  power: number;
  constructor(power: number) {
    this.power = power;
  }
}

const rocketFactory = new RocketFactory();
const rocket = rocketFactory.buildRocket();

두번째 예시는 위에서 추상화한 팩토리와 제품을 바탕으로 좀 더 구체적인 팩토리와 제품을 만든 예시 코드입니다.

import { Engine, Payload, Rocket, RocketFactory, Stage } from "./rocket";

export class Satellite extends Payload {
  constructor(public id: number) {
    super(200);
  }
}

export class FirstStage extends Stage {
  constructor() {
    super([new Engine(1000), new Engine(1000), new Engine(1000), new Engine(1000)]);
  }
}

export class SecondStage extends Stage {
  constructor() {
    super([new Engine(1000)]);
  }
}

type FreightRocketStages = [FirstStage, SecondStage];

class FreightRocketFactory implements RocketFactory {
  private satelliteId: number = 0;

  buildRocket(): Rocket {
    const rocket = new Rocket();
    const payload = this.createPayload();
    const stage = this.createStages();
    rocket.payload = payload;
    rocket.stage = stage;
    return rocket;
  }

  createPayload(): Satellite {
    return new Satellite(this.satelliteId++);
  }

  createStages(): FreightRocketStages {
    return [new FirstStage(), new SecondStage()];
  }
}

const freightRocketFactory = new FreightRocketFactory();
const freightRocket = freightRocketFactory.buildRocket();

Conclusion

사실 예시 코드는 그렇게 중요하지 않습니다. 팩토리 메서드의 개념과 유스케이스를 이해하는 것이 더 중요하다고 생각합니다.

다시 한번 정리해보죠.

팩토리 메서드는 객체를 생성하는 클래스이며 객체를 생성하기 위해 또 다른 팩토리 메서드를 사용할 수 있습니다.

또한, 추상화된 클래스가 아닌 조금 더 구체적인 제품을 생산하기 위해 상속하여 구현부를 변경할 수 있습니다. (최근 객체지향에 대해 공부를 하다 다형성에 대해 배웠는데 이 부분이 바로 다형성이 아닐까 하는 생각을 해봅니다.)

profile
세계 최고 수준을 향해 달려가는 개발자입니다.

0개의 댓글