728x90

1. 관찰자 패턴 ( Observer Pattern ) 정의

  • 객체 사이에 일 대 다의 의존 관계를 정의해두어, 어떤 객체의 상태가 변할 때 그 객체에 의존성을 가진 다른 객체들이 그 변화를 통지받고 자동으로 업데이트될 수 있게 만드는 패턴

 

2. 관찰자 인터페이스 정의

// 옵저버 클래스
class Observer
{
public:
    virtual ~Observer() {}

    virtual void OnNotify( const Entity& InEntity, Event InEvent ) = 0;
};

 

3. 관찰자 인터페이스 구현

// 업적 시스템에 옵저버 인터페이스 구현 추가
class Achievements : public Observer
{
public:
    virtual void OnNotify( const Entity& InEntity, Event InEvent ) override;
};

void Achievements::OnNotify( const Entity& InEntity, Event InEvent )
{
    switch ( InEvent )
    {
    case EVENT_LEVELUP:
        if ( InEntity.IsLevelUP() )
            // 레벨업 업적 이벤트 처리
        break;
    case EVENT_KILL_MONSTER:
        if ( InEntity.IsKillMonster())
             // 몬스터킬 업적 이벤트 처리
        break;
    }
}
  • 관찰자 인터페이스를 각각 시스템에 맞춰 정의하여 사용.

 

4. 관찰 대상 정의

// 관찰 대상자
class Subject
{
private:
    std::list< Observer* > observers;

protected:
    void Notify( const Entity& InEntity, Event InEvent );

public:
    // 관찰 대상을 추가한다.
    void AddObserver( Observer* InObserver );

    // 관찰 대상을 제거한다.
    void RemoveObserver( Observer* InObserver );
};

void Subject::Notify( const Entity& InEntity, Event InEvent )
{
    for ( auto& iter : observers)
		iter->OnNotify( InEntity, InEvent );
}
  • 관찰 대상 리스트에 추가 / 삭제하여 관찰 당하는 객체 OnNotity()를 호출한다.
  • 관찰 대상은 관찰자와 상호작용하지만, 서로 커플링되어 있지 않다.

 

5. 사라진 리스너 문제 ( Lapsed Listener Problem ) ★

  • UI를 열 때 관찰자를 등록한 뒤, UI를 닫을 때 관찰자를 제거하지 않으면 발생하는 문제
  • UI를 닫은 상태에서는 UI를 갱신할 필요가 없지만 관찰자를 제거하지 않아 알림이 올 때마다 UI가 갱신된다. ( CPU 연산 낭비 )
  • UI를 매번 새로 생성한 뒤, 관찰자를 등론한 경우 관찰 대상자에 메모리가 참조되고 있어 GC가 돌지 않는 문제가 발생한다.
  • ex ) 아이템 획득, 사용 등 빈번하게 발생하는 이벤트에서 가방을 갱신하도록 관찰자를 등록하고, 제거하지 않은 경우
반응형

+ Recent posts