728x90

객체의 상태는 객체 내부의 데이터 멤버들이 가지는 값에 의해 결정됩니다. 객체의 행위 수행은 해당 객체의 상태에 따라 다양하게 변경될 수 있기 때문에 분기 처리를 하는 경우가 많은데 만약 새로운 상태가 추가되었을 때 반영하기 어렵다는 단점이 있습니다. 

 

새로운 상태가 추가되더라도 기존 소스코드에 영향을 주지 않고 새로운 것을 추가하기 위해서는 클래스 상속을 이용해서 최상위 클래스에서 제공하는 인터페이스 형태로만 프로그램을 작성하면 됩니다. 이제 추가된 상태를 포함해서 객체의 상태가 변화가 있을 때마다 행위 수행 변경을 분기 수정 없이 처리하기 위해서는 다른 객체에게 상태 변화에 따른 행위 수행 변경을 위임하면 됩니다. 

 

위와 같은 방법을 게임 캐릭터라는 객체가 있을 때 등급이나 레벨에 따라 같은 공격을 수행했을 때 다른 기능을 내야한다고하면 아래와 같은 구조를 가지게 됩니다. 만약 새로운 등급 상태가 추가가 된다면 GameLevel 상태 객체를 상속받는 하위 객체를 정의하면 됩니다.

class GameLevel {
    static GameLevel* CreateInstance() { return 0; }
    virtual void Attack = 0;
protected:
    GameLevel() { }
};

class GameLevel1 : public GameLevel {
    static GameLevel* CreateInstance() {
        if ( pInstance == 0 ) { pInstance = new GameLevel1; } 
        return pInstance;
    }
    void Attack { cout << "Level1 Attack"; }
private:
    static GameLevel1* pInstance;
};
GameLevel1* GameLevel1::pInstance = 0;

class GameLevel2 : public GameLevel {
    static GameLevel* CreateInstance() {
        if ( pInstance == 0 ) { pInstance = new GameLevel1; } 
        return pInstance;
    }
    void Attack { cout << "Level2 Attack"; }
private:
    static GameLevel2* pInstance;
};
GameLevel2* GameLevel2::pInstance = 0;

class Player {
	Player() { pGameLevel = GameLevel1::CreateInstance(); }
    void UpgradeLevel(GameLevel* pLevel) { pGameLevel = pLevel; }
    void Attack() { pGameLevel->Attack(); }
private:
    GameLevel* pGameLevel;
};

int main()
{
    Player user;
    user.Attack();
    
    GameLevel* pGameLevel2 = GameLevel2::CreateInstance();
    user.upgradeLevel(pGameLevel2);
    user.Attack();
}
    

이처럼 객체 내부 상태 자체를 클래스로 정의하고 상속 구조를 이용해서 해당 상태의 분기 처리를 하지 않고 다형성을 통해 처리하는 구조를 상태 패턴이라고 합니다. 이 구조를 이용하면 하위 클래스 구조를 이용해 새로운 상태를 추가하기가 쉬워지고 상태가 추가되더라도 상태 변화에 따른 행위 수행 변경이 쉬워지게 됩니다.

728x90

'Programming > C++' 카테고리의 다른 글

C++ 템플릿 메소드 패턴  (0) 2021.06.20
c++ 전략 패턴  (0) 2021.06.20
C++ 옵저버 패턴  (0) 2021.06.13
C++ 메멘토 패턴  (0) 2021.06.10
C++ 중재자 패턴  (0) 2021.06.06

+ Recent posts