태크놀로지

커맨드 패턴이란? 본문

디자인 패턴

커맨드 패턴이란?

원택 2020. 9. 11. 01:14

커맨드 패턴이란?

요청 자체를 캡슐화하는 것입니다. 이를 통해 요청이 서로 다른 사용자를 매개변수로 만들고, 요청을 대기시키거나 로깅하여, 되돌릴 수 있는 연산을 지원합니다. 쉬운말로 누가 무엇을 해야할지에 대한 명령을 객체로 만들어 관리한다는 말입니다. 이 패턴은 예시의 사진을 보고 바로 구현하며 이해해봅시다.

 

실습 < AI가 몬스터들에게 명령을 내리는 상황 >

AI는 로직에 따라 대상에게 명령들을 내리면, 명령들이 큐에 차례대로 싸여 명령이 내려진 순서대로 대상이 명령을 수행하게 됩니다. 

 

실습코드

Command 인터페이스

class GameObject;
class Command abstract
{
protected:
	GameObject* m_Subject;
	int m_Message;

public:
	virtual void execute() = 0;

public:
	Command(GameObject* subject, int message) : m_Subject(subject), m_Message(message) {}
	virtual ~Command() = default;
};

Command 추상클래스는 명령을 전달할 주체(Subject)와 메시지를 저장하고 있습니다. execute로 명령을 수행합니다.

 

MonsterMoveCommand - 몬스터 이동과 관련된 명령커맨드

class MonsterMoveCommand : public Command
{
public:
	virtual void execute() override;

public:
	MonsterMoveCommand(GameObject* subject, int message) : Command(subject, message) {}
	virtual ~MonsterMoveCommand() = default;
};
void MonsterMoveCommand::execute()
{
	switch (m_Message)
	{
	case AI::MESSAGE_MONSTER_ATTACK: {
		cout << m_Subject->GetName() << " - Monster Attack" << endl;
		break;
	}
	case AI::MESSAGE_MONSTER_RUN: {
		cout << m_Subject->GetName() << " - Monster Run" << endl;
		break;

	}
	case AI::MESSAGE_MONSTER_STAY: {
		cout << m_Subject->GetName() << " - Monster Stay" << endl;
		break;

	}
	case AI::MESSAGE_MONSTER_DIE: {
		cout << m_Subject->GetName() << " - Monster Die" << endl;
		break;

	}
	default:
		break;
	}
}

명령 메시지에 따라 명령을 수행하고 있습니다. 명령 대상의 포인터를 알고있어 주체에 접근이 가능합니다. 즉 AI에 따라 게임오브젝트의 애니메이션이 변경되거나 월드행렬 포지션등 변경이 가능합니다.

 

CommandHandler - 명령을 하고 수행하는 명령들을 관리하는 메서드를 제공

std::queue<Command*> g_CommandQueue;

namespace CommandHandler
{
	template<class tCommand>
	void PushCommand(int message, GameObject* subj)
	{
		Command* cmd = new tCommand(subj, message);
		g_CommandQueue.push(cmd);
	}

	void ExecuteCommand()
	{
		if (g_CommandQueue.empty()) return;

		g_CommandQueue.front()->execute();
		g_CommandQueue.pop();
	}
}

void PushCommand() - 누구에게 무슨 명령을 전달하기 위해, 누구(GameObject) 무슨 명령(message)를 파라미터로 넘겨주어 커맨드큐에 밀어넣습니다.

void ExecuteCommand() - 큐에 특성에 따라 명령이 내려진 순서대로 앞에서부터 명령을 실행하고 큐에서 제거합니다.

 

Main

int main()
{
	// 몬스터 생성
	for (int i = 0; i < 5; ++i)
	{
		g_GameObjects.push_back(new GameObject("Monster" + to_string(i)));
	}

	// AI에서 명령메시지를 큐에 전달
	CommandHandler::PushCommand<MonsterMoveCommand>(AI::MESSAGE_MONSTER_ATTACK, g_GameObjects[0]);
	CommandHandler::PushCommand<MonsterMoveCommand>(AI::MESSAGE_MONSTER_DIE, g_GameObjects[2]);
	CommandHandler::PushCommand<MonsterMoveCommand>(AI::MESSAGE_MONSTER_RUN, g_GameObjects[1]);

	while (true) {
		// 큐에서 차례대로 명령메시지를 수행함
		CommandHandler::ExecuteCommand();
	}
}

> 결과창

차례대로 명령들이 수행된것을 볼 수 있습니다.

'디자인 패턴' 카테고리의 다른 글

단점을 보안한 옵저버 패턴  (0) 2020.09.15
옵저버 패턴이란?  (0) 2020.09.13
컴포넌트 패턴이란  (0) 2020.09.08
인덱스를 사용한 씬관리 방법  (0) 2020.09.03
싱글턴 패턴이란  (0) 2020.09.02