커맨드(Command) 패턴

2024. 10. 17. 00:47Design Pattern

Command 패턴 - 개념과 구현

Command 패턴행위 패턴(Behavioral Pattern) 중 하나로, 요청을 객체로 캡슐화하여 요청을 보낸 사람과 요청을 처리하는 사람을 분리하는 패턴입니다. 이 패턴은 명령을 실행하는 방법과 관련된 다양한 설정을 처리할 수 있게 해주며, 요청을 큐에 저장하거나 로그로 기록하는 등 여러 기능을 추가하는 데 유용합니다.


1. Command 패턴이란?

Command 패턴은 다음과 같은 상황에서 유용합니다:

  • 요청을 객체로 캡슐화하여 매개변수를 조작할 수 있게 하고, 요청을 실행하는 객체와 요청을 수신하는 객체를 분리합니다.
  • 요청을 큐에 추가하거나 로그를 남기고 싶을 때.
  • Undo 및 Redo 기능을 제공할 때.

2. Command 패턴의 구조

Command 패턴은 다음과 같은 구성 요소로 이루어져 있습니다:

1. Command

  • 명령을 정의하는 인터페이스로, Execute 메서드를 포함합니다.

2. ConcreteCommand

  • Command 인터페이스를 구현하며, 요청을 수신하고 실행하는 객체에 대한 참조를 유지합니다.

3. Invoker

  • 명령을 요청하는 객체로, 명령을 실행하는 메서드를 호출합니다.

4. Receiver

  • 실제 명령을 수행하는 객체입니다.

3. Command 패턴의 구현 예시 (C#)

// Command: 명령 인터페이스
public interface ICommand
{
    void Execute();
}

// Receiver: 명령을 수행하는 클래스
public class Light
{
    public void TurnOn()
    {
        Console.WriteLine("Light is On");
    }

    public void TurnOff()
    {
        Console.WriteLine("Light is Off");
    }
}

// ConcreteCommand: 구체적인 명령 클래스
public class TurnOnLightCommand : ICommand
{
    private Light _light;

    public TurnOnLightCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOn(); // 요청 수행
    }
}

public class TurnOffLightCommand : ICommand
{
    private Light _light;

    public TurnOffLightCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOff(); // 요청 수행
    }
}

// Invoker: 명령을 요청하는 클래스
public class RemoteControl
{
    private ICommand _command;

    public void SetCommand(ICommand command)
    {
        _command = command;
    }

    public void PressButton()
    {
        _command.Execute(); // 명령 실행
    }
}

위의 코드에서 ICommand는 명령 인터페이스이며, Light는 실제 요청을 수행하는 수신자입니다. TurnOnLightCommand와 TurnOffLightCommand는 구체적인 명령을 정의하고, RemoteControl은 명령을 요청하는 인보커입니다.

클라이언트 코드

public class Program
{
    public static void Main(string[] args)
    {
        Light light = new Light(); // 수신자
        ICommand turnOn = new TurnOnLightCommand(light); // 구체적인 명령
        ICommand turnOff = new TurnOffLightCommand(light); // 구체적인 명령

        RemoteControl remote = new RemoteControl(); // 인보커

        remote.SetCommand(turnOn); // 켜기 명령 설정
        remote.PressButton(); // Light is On

        remote.SetCommand(turnOff); // 끄기 명령 설정
        remote.PressButton(); // Light is Off
    }
}

클라이언트 코드에서는 Light 객체를 생성하고, TurnOnLightCommand와 TurnOffLightCommand를 만들어 RemoteControl에 명령을 설정합니다. 버튼을 누르면 해당 명령이 실행됩니다.


4. Command 패턴의 장단점

장점:

  • 요청의 캡슐화: 요청을 객체로 캡슐화하여 메서드 호출을 단순화하고 다양한 요청을 처리할 수 있습니다.
  • Undo 및 Redo 기능: 명령을 객체로 만들면 요청을 큐에 저장하여 나중에 실행하거나 실행 취소할 수 있습니다.
  • 확장성: 새로운 명령을 추가할 때 기존 코드를 수정할 필요가 없습니다.

단점:

  • 명령 클래스의 수 증가: 많은 명령을 처리해야 할 경우 클래스의 수가 급격히 증가할 수 있습니다.
  • 복잡성 증가: 초기 설계가 복잡해질 수 있으며, 명령을 관리하는 방법이 필요합니다.

5. Command 패턴의 사용 사례

5.1. GUI 애플리케이션

버튼 클릭, 메뉴 선택 등 다양한 사용자 입력을 캡슐화하여 실행하고, Undo 및 Redo 기능을 쉽게 구현할 수 있습니다.

5.2. 게임 개발

게임에서 사용자 입력을 처리하거나, 공격, 방어 등 다양한 액션을 명령 객체로 캡슐화하여 유연한 조작을 가능하게 할 수 있습니다.

5.3. 서버 요청 처리

서버에서 클라이언트의 요청을 명령 객체로 처리하여, 요청 큐를 관리하거나 로그를 기록할 수 있습니다.


Command 패턴은 요청을 객체로 캡슐화하여 요청을 보낸 사람과 처리하는 사람을 분리함으로써 코드의 유연성을 높이고 관리하기 쉽게 만들어주는 행위 패턴입니다. 이 패턴을 이해하고 적용함으로써, 더 나은 소프트웨어 설계를 할 수 있습니다.

'Design Pattern' 카테고리의 다른 글

중재자(Mediator) 패턴  (1) 2024.10.17
이터레이터(Iterator) 패턴  (1) 2024.10.17
브릿지(Bridge) 패턴  (0) 2024.10.17
프록시(Proxy) 패턴  (0) 2024.10.17
컴포지트(Composite) 패턴  (0) 2024.10.17