본문 바로가기

Computer Science/Design Pattern

[게임 프로그래밍 패턴] 12. 타입 객체 패턴

타입 객체 패턴 (Type Object Pattern)

239 : 클래스 하나를 인스턴스별로 다른 객체형으로 표현할 수 있게 만들어, 새로운 '클래스들'을 유연하게 만들 수 있게 한다.

타입 객체 패턴

타입 객체 클래스와 타입 사용 객체 클래스를 정의한다. 타입 사용 객체는 자신의 타입을 나타내는 타입 객체를 참조한다. 상속 처리를 하드코딩하지 않고서도 마치 상속받는 것처럼 비슷한 객체끼리 데이터나 동작을 공유할 수 있다.

언제 쓸 것인가?

  1. 나중에 어떤 타입이 필요할 지 알 수 없다.
  2. 컴파일이나 코드 변경 없이 새로운 타입을 추가하거나 타입을 변경하고 싶다.

주의사항

  1. 타입 객체를 직접 관리해야 한다.
    - 타입 객체를 생성하고, 이를 필요로 하는 몬스터가 있는 한 메모리에 유지해야 한다. 몬스터 인스턴스를 생성할 때 알맞은 종족 객체 레퍼런스로 초기화하는 것도 우리의 몫이다.
  2. 타입별로 동작을 표현하기가 더 어렵다.
    - 상속 방식에서는 메서드를 오버라이드해서 코드로 값을 계산하거나 다른 코드를 호출하는 등 마음대로 할 수 있다. 하지만 타입 객체 패턴에서는 타입 종속적인 데이터를 정의하기는 쉽지만, 타입 종속적인 동작을 정의하기는 어렵다.

예제코드

public class Breed {
    private int health;
    private String attack;
    public Breed(int health, String attack) {
        this.health = health;
        this.attack = attack;
    }
    int getHealth() {
        return this.health;
    }
    String getAttack() {
        return this.attack;
    }
}
public class Monster {
    private int health;
    private Breed breed;
    public Monster(Breed breed) {
        this.health = breed.getHealth();
    }
    String getAttack() {
        return breed.getAttack();
    }
}

디자인 결정

  1. 타입 객체를 숨길 것인가? 노출할 것인가?
    1. 타입 객체를 캡슐화
      - 타입 객체 패턴의 복잡성이 나머지 다른 코드에는 드러나지 않는다.
      - 타입 사용 객체는 타입 객체로부터 동작을 선택적으로 오버라이드할 수 있다.
      - 타입 객체 메서드를 전부 포워딩해야 한다.
    2. 타입 객체를 노출
      - 타입 사용 클래스 인스턴스를 통하지 않고도 외부에서 타입 객체에 접근할 수 있따.
      - 타입 객체가 공개 API의 일부가 된다.
  2. 타입 사용 객체를 어떻게 생성할 것인가?
    1. 객체를 생성한 뒤에 타입 객체를 넘겨주는 경우
      - 외부 코드에서 메모리 할당을 제어할 수 있다.
    2. 타입 객체의 '생성자' 함수를 호출하는 경우
      - 타입 객체에서 메모리 할당을 제어한다.
  3. 타입을 바꿀 수 있는가?
    1. 타입을 바꿀 수 없다면
      - 코드를 구현하고 이해하기가 더 쉽다.
      - 디버깅하기 쉽다.
    2. 타입을 바꿀 수 있다면
      - 객체 생성 횟수가 줄어든다.
      - 가정을 깨지 않도록 주의해야 한다.
  4. 상속을 어떻게 지원할 것인가?
    1. 상속 없음
      - 단순하지만 중복 작업을 해야할 수도 있다.
    2. 단일 상속
      - 단순한 편이다.
      - 속성 값을 얻는데 오래 걸린다.
    3. 다중 상속
      - 거의 모든 데이터 중복을 피할 수 있다.
      - 복잡하다.