Deff_Dev

[디자인 패턴] 명령 패턴 (Command Pattern) 본문

CS/디자인 패턴

[디자인 패턴] 명령 패턴 (Command Pattern)

Deff_a 2024. 11. 7. 00:08

⚒️ 명령 패턴이 뭘까 ?

https://refactoring.guru/ko/design-patterns/command

 

명령 패턴은 메서드 호출을 실체화 한 것 이다.

  • 함수 호출을 객체로 감쌌다라는 의미

⇒ 콜백을 객체지향적으로 표현

 

실체화란 ?

→ 어떤 개념을 변수에 저장하거나 함수에 전달할 수 있도록 객체로 바꿀 수 있다는 걸 의미

 

특징

  • 작업을 캡슐화하여 하나의 명령을 실행
  • 기능 실행, 취소 재실행할 때 적합
  • 일반적으로 1 대 1 관계
  • 하나의 수신자(리시버)에 대해 하나의 명령이 실행

 

명령 패턴의 좋은 예시

리플레이를 구현할 때, 매 프레임마다 전체 게임 상태를 저장해도 되지만 해당 방법은 너무 많은 메모리가 필요하다.

그렇기 때문에, 명령 패턴을 사용하여, 전체 개체가 실행하는 명령 모두를 매 프레임마다 저장하여 리플레이할 때는 이전에 저장한 명령들을 순서대로 실행하여 게임을 시뮬레이션한다.

 

[플레이어 이동 관련 명령 패턴 코드]

더보기
// 명령 인터페이스
public interface ICommand
{
    void Execute();
    void Undo();
}

// 구체적인 명령 클래스
public class MoveCommand : ICommand
{
    private Transform playerTransform;
    private Vector3 direction;
    private float distance;

    public MoveCommand(Transform player, Vector3 dir, float dist)
    {
        playerTransform = player;
        direction = dir;
        distance = dist;
    }

    public void Execute()
    {
        playerTransform.Translate(direction * distance);
    }

    public void Undo()
    {
        playerTransform.Translate(-direction * distance);
    }
}

// 명령을 실행하는 인보커 클래스
public class PlayerController : MonoBehaviour
{
    public Transform player;
    private Stack<ICommand> commandHistory = new Stack<ICommand>();

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            ICommand moveCommand = new MoveCommand(player, Vector3.forward, 1f);
            moveCommand.Execute();
            commandHistory.Push(moveCommand);
        }

        if (Input.GetKeyDown(KeyCode.Z) && commandHistory.Count > 0)
        {
            ICommand lastCommand = commandHistory.Pop();
            lastCommand.Undo();
        }
    }
}

🥴 명령 패턴 vs 옵저버 패턴

명령 패턴을 처음 봤을 때, 직 직접적인 객체 참조 대신 추상화된 인터페이스를 통해 작업을 실행한다는 점에서 우리가 흔히 사용하는 옵저버 패턴과 유사하다고 생각했다.

 

[명령 패턴과 옵저버 패턴의 차이점]

패턴 이름 목적 사용 관계
명령 패턴 하나의 수신자(리시버)에 대해 하나의 명령이 실행 기능 실행, 취소 재실행하는 작업이 필요할 때 적합 1:1 관계
옵저버 패턴 하나의 객체의 상태 변화를 여러 객체(옵저버)들에게 알림 객체간 상태 동기화 작업이 필요할 때 적합 1:N 관계