๋ช…๋ น(Command) ํŒจํ„ด

2023. 6. 5. 17:58ยท๐Ÿ–ฅ๏ธ Study Note/Design Patteren

{ ๋ช…๋ น ํŒจํ„ด์ด๋ž€? }

๋ช…๋ น ํŒจํ„ด์€ GoF์˜ ํ–‰์œ„ ํŒจํ„ด ์ค‘ ํ•˜๋‚˜๋กœ,

์š”์ฒญ(๋ช…๋ น)์„ ๊ฐ์ฒด์˜ ํ˜•ํƒœ๋กœ ์บก์Аํ™”ํ•˜์—ฌ ์žฌ์ด์šฉํ•˜๊ฑฐ๋‚˜ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๋„๋ก ์š”์ฒญ์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ๋กœ๊ทธ์— ๋‚จ๊ธฐ๋Š” ํŒจํ„ด์ด๋‹ค.

๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ์„ ๊ฐ์ฒด๋กœ ๊ฐ์‹ผ ํ˜•ํƒœ์ด๋‹ค.

์ฝœ๋ฐฑ์„ ๊ฐ์ฒด ์ง€ํ–ฅ์ ์œผ๋กœ ์„ค๊ณ„ํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ข‹๋‹ค.

์š”์ฒญ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ข… ๋ช…๋ น์–ด๋“ค์€ ์ถ”์ƒ ํด๋ž˜์Šค์™€ ๊ตฌ์ฒด ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๋‹จ์ˆœํ™”ํ•œ๋‹ค.

{ ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์—์„œ ๋ช…๋ น ํŒจํ„ด ํ™œ์šฉํ•˜๊ธฐ : ์บ๋ฆญํ„ฐ ์กฐ์ž‘ }

๊ฒŒ์ž„ ๊ฐœ๋ฐœ์˜ ๋‹ค์–‘ํ•œ ๋ถ€๋ถ„์—์„œ ๋ช…๋ น ํŒจํ„ด์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ,

'๋ช…๋ น' ํ•˜๋ฉด ๊ฐ€์žฅ ๋จผ์ € ์ƒ๊ฐ๋‚˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ž…๋ ฅ(๋ช…๋ น)์— ๋”ฐ๋ผ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์›€์ง์ด๋Š” ๋กœ์ง์„ ๋ช…๋ น ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ณด์ž.

๋ช…๋ น ํŒจํ„ด์„ ์ ์šฉํ•˜๊ธฐ ์ „ ์ฝ”๋“œ

void CInputHandler::HandleInput()
{
	if(isPressed(KEY::SPACE)) CPlayer::Jump();
    else if(isPressed(KEY::E)) CPlayer::UseSkill();
    else if(isPressed(KEY::CTRL)) CPlayer::Crouch();
}

์œ„ ์ฝ”๋“œ๋Š” ํŠน์ • ํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ํ”Œ๋ž˜์ด์–ด ์บ๋ฆญํ„ฐ๊ฐ€ ์ ์ ˆํ•œ ๋™์ž‘์„ ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

์ด ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ๋Š” ์‰ฝ์ง€๋งŒ ๋‹จ์ ์ด ์žˆ๋‹ค.

์šฐ์„   key ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

๋˜ํ•œ ํ”Œ๋ ˆ์ด์–ด์˜ ํŠน์ • ๋™์ž‘์—๋งŒ ๋ฐ”์ธ๋”ฉ์ด ๋˜์–ด ๋ฒ”์šฉ์ ์ด์ง€ ๋ชปํ•˜๋‹ค.

 

์ด ์ฝ”๋“œ๋ฅผ ๋ช…๋ น ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์กฐ๊ธˆ ๋” ์œ ์—ฐํ•˜๊ณ  ๋ฒ”์šฉ์ ์ธ ์ฝ”๋“œ๋กœ ๋งŒ๋“ค์–ด๋ณด์ž.

๋ช…๋ น ํŒจํ„ด์„ ์ ์šฉํ•˜์ž

1. ๋ช…๋ น๋“ค์˜ ๊ณตํ†ต ์ƒ์œ„ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.

class Command
{
public:
	virtual ~Command();
    virtual void execute() = 0;
}
  • Command๋ผ๋Š” ๊ฐ์ฒด๋กœ execute()๋ผ๋Š” ๋ช…๋ น์„ ๊ฐ์‹ผ ํ˜•ํƒœ์ด๋‹ค.
  • ๊ธฐ๋ฐ˜ ํด๋ž˜์Šค์˜ ์†Œ๋ฉธ์ž์— virtual ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋ง์ž.

2. ํ–‰๋™ ๋ณ„๋กœ ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.

class CJumpCommand : public Command
{
public:
	virtual void execute() { CPlayer::Jump(); }
};

class CUseSkillCommand : public Command
{
public:
	virtual void execute() { CPlayer::UseSkill(); }
};

class CCrouchCommand : public Command
{
public:
	virtual void execute() { CPlayer::Crouch(); }
};

3. InputHandler์— ๊ฐ ๋ฒ„ํŠผ ๋ณ„๋กœ ๋ฐ”์ธ๋“œ ๋  Command ํด๋ž˜์Šค ํฌ์ธํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค.

  • ์ž…๋ ฅ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๋ฒ„ํŠผ์˜ Command->execute()ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
class CInputHandler
{
public:
	void HandleInput();

private:
	Command* m_btn_space_command;
    Command* m_btn_e_command;
    Command* m_btn_ctrl_command;
}

void CInputHandler::HandleInput
{
	if(isPressed(KEY::SPACE)) m_btn_space_command->execute();
    else if(isPressed(KEY::E)) m_btn_e_command->execute();
    else if(isPressed(KEY::CTRL)) m_btn_ctrl_command->execute();
}

๋” ๊ฐœ์„ ํ•  ์ˆ˜ ์—†์„๊นŒ?

๋ช…๋ น ํŒจํ„ด์„ ํ™œ์šฉํ•ด์„œ InputHandler์™€ Player์˜ ์ปคํ”Œ๋ง์„ ํ•ด์†Œํ–ˆ๋‹ค.

์ด์ œ ๋™์ž‘์— ๋”ฐ๋ผ key ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋˜ํ•œ ์–ด๋А ๋™์ž‘์ด๋“ ์ง€ key์— ๋ฐ”์ธ๋”ฉํ•˜์—ฌ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

์„ค๋ น ๊ทธ ๋™์ž‘์ด Player์™€ ๊ด€๋ จ๋œ ๋™์ž‘์ด ์•„๋‹ˆ์–ด๋„ ๊ดœ์ฐฎ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ์ „ํžˆ ํ•œ๊ณ„์ ์€ ์žˆ๋‹ค.

JumpCommand์™€ ๊ฐ™์€ Command๋“ค์€ Player์—๋งŒ ํ•œ์ •๋˜์–ด์žˆ๋‹ค.

๋”ฐ๋ผ์„œ ๊ฐ™์€ ์ข…๋ฅ˜์˜ ์›€์ง์ž„์„ ๋ช…๋ นํ•˜๋Š” Command๋ผ๋„ ํด๋ž˜์Šค ๋ณ„๋กœ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•œ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด Monter์˜ Jump Command๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ํ•˜๋ฉด,

Monster1JumpCommand,Monster2JumnpCommand, ... ์ฒ˜๋Ÿผ

๋ชฌ์Šคํ„ฐ ์ข…๋ฅ˜ ๋ณ„๋กœ ๋ณ„๋„์˜ JumpCommand ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด์ค˜์•ผ ํ•œ๋‹ค.

 

๋งŒ์•ฝ ์ด๋Ÿฐ Command๋“ค์ด Player์™€ ๊ฐ™์€ ํŠน์ • ํด๋ž˜์Šค์— ํ•œ์ •๋˜์–ด์žˆ์ง€ ์•Š๊ณ 

๋ชจ๋“  ์›€์ง์ผ ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค(Actor)๋“ค์—๊ฒŒ ๊ณตํ†ต์œผ๋กœ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ๋ฒ”์šฉ์„ฑ์ด ์ข‹์ง€ ์•Š์„๊นŒ?

Command ๊ฐœ์„ ํ•˜๊ธฐ

1. Command์˜ ๋™์ž‘ ์ฃผ์ฒด๋ฅผ ์™ธ๋ถ€์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

class Command
{
public:
	virtual ~Command() {};
    virtual void execute(GameActor& actor) = 0;
}

2. Command๋ฅผ ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค๋“ค์ด actor๋ฅผ ํ™œ์šฉํ•˜๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค.

class CJumpCommand : public Command
{
public:
	//virtual void execute() { CPlayer::Jump(); }
	virtual void execute(GameActor& _actor)
    {
    	_actor.Jump();
    }
};

class CUseSkillCommand : public Command
{
public:
	//virtual void execute() { CPlayer::UseSkill(); }
	virtual void execute(GameActor& _actor)
    {
    	_actor.UseSkill();
    }

};

class CCrouchCommand : public Command
{
public:
	//virtual void execute() { CPlayer::Crouch(); }
    virtual void execute(GameActor& _actor)
    {
    	_actor.Crouch();
    }
};

3. CInputHandler์—์„œ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฌ๋ฉด Command๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค.

// Command.cpp

Command* CInputHandler::handleInput()
{
	if(isPressed(KEY::SPACE))  return m_btn_space_command;
    else if(isPressed(KEY::E)) return m_btn_e_command;
    else if(isPressed(KEY::CTRL)) return m_btn_ctrl_command;

    else return nullptr;
}

4. ๋ฐ˜ํ™˜๋œ Command๋Š” GameActor๊ฐ€ ๋ฐ›์•„, GameActor์— ๋“ฑ๋กํ•ด ๋‘” Actor๋ฅผ ์ธ์ž๋กœ ๋„ฃ์–ด Command์˜ execute()๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

// CGameActor.cpp
// CGameActor๋Š” ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ static CGameActor* m_actor ์†Œ์œ .

void CGameActor::ControlActor()
{
	Command* c = CInputHandler::handleInput();
    if(c)
    {
    	c->execute(m_actor);
    }

}

์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ๋ชจ๋“  GameActor๋ฅผ ์ƒ์†๋ฐ›๋Š” ๊ฐ์ฒด๋“ค์„ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์กฐ์ข…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

{ ๋ช…๋ น ์‹คํ–‰ ์ทจ์†Œ์™€ ์žฌ์‹คํ–‰ }

๋ช…๋ น ํŒจํ„ด์„ ํ™œ์šฉํ•˜๋ฉด ๋ช…๋ น ์‹คํ–‰ ์ทจ์†Œ์™€ ์žฌ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ช…๋ น ์‹คํ–‰ ์ทจ์†Œ

์šฐ์„  Command์— undo()ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

Command๋Š” execute()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์ €์žฅํ•ด๋‘” ๋’ค์— ๋ช…๋ น์„ ์‹คํ–‰ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  undo()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์ €์žฅํ•ด๋‘์—ˆ๋˜ ์ƒํƒœ๋กœ ๋Œ์•„๊ฐ€๋ฉด ๋œ๋‹ค.

๋‹ค์ค‘ ๋ช…๋ น ์‹คํ–‰ ์ทจ์†Œ, ์žฌ์‹คํ–‰

๋‹ค์ค‘ ๋ช…๋ น ์‹คํ–‰ ์ทจ์†Œ๋„ ์–ด๋ ต์ง€ ์•Š๋‹ค.

์ตœ๊ทผ n๊ฐœ์˜ ๋ช…๋ น์„ ์ €์žฅํ•˜๋Š” ๋ฐฐ์—ด(๋ช…๋ น ์ŠคํŠธ๋ฆผ)์„ ๋‘๊ณ , ํ˜„์žฌ ๋ช…๋ น์„ ๊ฐ€๋ฅดํ‚ค๋Š” ํฌ์ธํ„ฐ๋งŒ ์žˆ์œผ๋ฉด ๋œ๋‹ค.

๋งŒ์•ฝ ์œ„ ๊ทธ๋ฆผ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ๋ช…๋ น ์ทจ์†Œํ•˜๋ฉด, Current ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” Command์—์„œ undo()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  Current๊ฐ€ ๋’ค์˜ Command๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•˜๋ฉด ๋œ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์—ฌ๋Ÿฌ๋ฒˆ undo()๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๋ช…๋ น ์ทจ์†Œ๋ฅผ ์ทจ์†Œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์ฆ‰, ์žฌ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด undo()์ดํ›„ Current ํฌ์ธํ„ฐ๊ฐ€ ๊ฐ€๋ฅดํ‚ค๊ณ  ์žˆ๋Š” Command์˜ execute()๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

 

Current์—์„œ undo()๋ฅผ ์‹คํ–‰ํ•œ ๋’ค, ์ƒˆ๋กœ์šด ๋ช…๋ น์ด ์ถ”๊ฐ€๋˜๋ฉด Current๋’ค์˜ ๋ช…๋ น๋“ค์„ ๋ชจ๋‘ ์‚ญ์ œํ•œ ๋’ค์— ์ƒˆ๋กœ์šด ๋ช…๋ น์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

 

 

๋„์„œ : ๊ฒŒ์ž„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจํ„ด

์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋ณ€๊ฒฝ๊ธˆ์ง€ (์ƒˆ์ฐฝ์—ด๋ฆผ)

'๐Ÿ–ฅ๏ธ Study Note > Design Patteren' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

ํ”„๋กœํ† ํƒ€์ž…(ProtoType) ํŒจํ„ด  (0) 2023.06.19
๊ด€์ฐฐ์ž(Observer) ํŒจํ„ด  (0) 2023.06.08
๊ฒฝ๋Ÿ‰(FlyWeight) ํŒจํ„ด  (2) 2023.06.07
๋””์ž์ธ ํŒจํ„ด์ด๋ž€?  (0) 2023.06.05
'๐Ÿ–ฅ๏ธ Study Note/Design Patteren' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • ํ”„๋กœํ† ํƒ€์ž…(ProtoType) ํŒจํ„ด
  • ๊ด€์ฐฐ์ž(Observer) ํŒจํ„ด
  • ๊ฒฝ๋Ÿ‰(FlyWeight) ํŒจํ„ด
  • ๋””์ž์ธ ํŒจํ„ด์ด๋ž€?
Beankong_
Beankong_
์ฃผ๋‹ˆ์–ด ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋ž˜๋จธ ๊ณต๋ถ€ ๊ธฐ๋ก
  • Beankong_
    Beankong's Devlog
    Beankong_
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ์ „์ฒด ๊ธ€ (145) N
      • โ›… Daily (0)
      • ๐Ÿ–ฅ๏ธ Study Note (1) N
        • C++ (1) N
        • Unreal Engine (5)
        • Coding Test (123)
        • Design Patteren (5)
        • VCS (Git..) (1)
        • Server (1)
      • ๐Ÿงญ Devlog (8) N
        • ์˜ค๋‹ต๋…ธํŠธ (4) N
        • UE5 GameLift Server Test Project (1)
        • TIL (3)
  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
Beankong_
๋ช…๋ น(Command) ํŒจํ„ด
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”