명령 패턴

패턴에 대한 이야기는 사실 지금 읽고 있는 디자인 패턴 책을 다 읽고 한번 적용해보고 이해한 후 다시 해보려고 했다. 하지만 지금 잘 모르는 상태에서 우선 글을 쓰고 나중에 좀 더 이해가 된 후에 비교해보는 것도 좋겠다라는 생각이 들어서 미숙한 상태지만 어떻게든 써보려고 한다.

디자인 패턴을 둘러 보기에 앞서 왜 디자인 패턴이 필요한지에 대한 이유를 간단하게 들자면 가독성과 수정용이성이다. 가독성은 무슨 말인지 쉽게 알 것이다. 코드가 한눈에 구분이 잘 되고 읽고 이해가 잘되는 것. 하지만 수정용이성은 다소 이해가 어려울 수 있다. 수정용이성은 코드들 간의 커플링(간섭)이 적게 하는 것이 관점이며, 가독성도 수정용이성에 어느정도 포함되어 있다. 일단 다른 사람이 읽어서 코드를 쉽게 파악이 가능해야 코드를 수정하기도 쉽기 때문이다. 코드들간의 필요 없는 간섭을 최소화 하고자 하는 것은 내가 수정하는 코드가 다른 코드와 연관이 되어 있어서 수정 시 다른코드까지 고려하거나 코드를 수정하며 어딘가 있을지 모르는 연관코드로 인해 알지 못하는 오류가 터지는 것을 방지하기 위함이다.

처음 다룰 명령 패턴은 내가 보기에는 입력과 동작을 구분한다고 받아들여졌다. 예시로 나와있는 것을 보면 예를 들어 ‘A버튼을 누르면 점프를 한다’라는 등의 입력에 대한 동작부분을 보면

if (isPressed(Button_A))
{
    Jump();
}
else if (isPressed(Button_B))
{
    Attack();
}
else if (isPressed(Button_X))
{
    WeaponSwap();
}
cs

라는 식의 코드가 될 것이다.
여기서 각 명령 자체를 하나의 클래스, 객체로 만들어서 사용하는 방식이 명령 패턴의 핵심이다.

class Command
{
public:
    virtual void execute() = 0;
};
class JumpCommand : public Command
{
public:
    virtual void execute() {Jump();}
};
class AttackCommand : public Command
{
public:
    virtual void execute() {Attack();}
};
class WeaponSwapCommand : public Command
{
public:
    virtual void execute() {WeaponSwap();}
};
class InputHandler
{
public:
    void handleInput()
    {
        if (isPressed(BUTTON_A)) Command_A>execute();
        else if (isPressed(BUTTON_B)) Command_B>execute();
        else if (isPressed(BUTTON_X)) Command_X>execute();
    }
private:
    Command* Command_A;
    Command* Command_B;
    Command* Command_X;
}
cs

보자마자 코드가 다소 복잡해 보이거나 오히려 수정이 더 힘들겠다라는 느낌이 들 수 있지만, 길어진 코드를 보기 싫다고 생각하지말고 차근차근 코드를 보자. 각 커맨드가 포인트로 되어 있어 동적할당을 통해 런타임에도 변경해졌고, 혹여 변경해야 할 때는 각 Command에 어떤 자식 클래스를 넣을지 수정해주면 된다.

큰 특징은 런타임에 각 키에 대한 재설정이 가능해지면서 조작법을 변경하기 위해서 재컴파일 할 필요가 없어졌다는 것이다. 키설정 옵션창을 만들어줘야 하는 번거로움은 생겼지만 유저가 키가 불편해서 재설정이 필요하다고 요청할 때 다시 컴파일하여 배포할 필요가 없어진다.

또 추가하여 생각해보면 각 명령이 하나의 객체가 되면서 명령의 큐잉한결 쉬워지게된다. Command의 큐를 하나 만들어 저장하면 된다. 이렇게 큐잉이 한결 쉬워지면 실행취소 및 재실행등의 추가 구현하기가 쉬워지게 된다.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s