디자인패턴

커맨드 패턴(Command Pattern)

ppp5500 2022. 4. 4. 20:50

커맨드 패턴은 실행될 기능을 캡슐화함으로써 기능의 실행을 요구하는 호출자(Invoker) 클래스와 실제 기능을 실행하는 수신자(Receiver) 클래스 사이의 의존성을 제거한다. 따라서 실행될 기능의 변경에도 호출자 클래스를 수정 없이 그대로 사용할 수 있도록 해준다.

Command: 실행될 기능에 대한 인터페이스. 실행될 기능을 execute 메서드로 선언함

ConcreteCommand: 실제로 실행되는 기능을 구현. 즉, Command라는 인터페이스를 구현함

Invoker: 기능의 실행을 요청하는 호출자 클래스

Receiver: ConcreteCommand에서 execute 메서드를 구현할 때 필요한 클래스. 즉, ConcreteCommand의 기능을 실행하기 위해 사용하는 수신자 클래스

 

// 커맨드 패턴 구현

Lamp lamp = new Lamp();
Command lampOnCommand = new LampOnCommand(lamp);

Button button1 = new Button(lampOnCommand);
button1.pressed();

Alarm alarm = new Alarm();
Command alarmOnCommand = new AlarmOnCommand(alarm);

Button button2 = new Button(alarmOnCommand);
button2.pressed();

button1 = new Button(alarmOnCommand);
button1.pressed(); // 알람 기능으로 바뀜

public interface Command
{
    public abstract void execute();
}

public class Button
{
    private Command theCommand;

    public Button(Command theCommand)
    {
        SetCommand(theCommand);
    }

    public void SetCommand(Command newCommand)
    {
        this.theCommand = newCommand;
    }

    public void pressed()
    {
        theCommand.execute();
    }
}

public class Lamp
{
    public void TurnOn()
    {
        Console.WriteLine("Lamp On");
    }
}

public class LampOnCommand : Command
{
    private Lamp theLamp;

    public LampOnCommand(Lamp theLamp)
    {
        this.theLamp = theLamp;
    }

    public void execute()
    {
        theLamp.TurnOn();
    }
}

public class Alarm
{
    public void Ringing()
    {
        Console.WriteLine("Alarm Ringing");
    }
}

public class AlarmOnCommand : Command
{
    private Alarm theAlarm;

    public AlarmOnCommand(Alarm theAlarm)
    {
        this.theAlarm = theAlarm;
    }
    public void execute()
    {
        theAlarm.Ringing();
    }
}

실행결과

Lamp lamp = new Lamp();
Command lampOnCommand = new LampOnCommand(lamp);

Button button1 = new Button(lampOnCommand);
button1.pressed();

Alarm alarm = new Alarm();
Command alarmOnCommand = new AlarmOnCommand(alarm);

Button button2 = new Button(alarmOnCommand);
button2.pressed();

button1 = new Button(alarmOnCommand);
button1.pressed(); // 알람 기능으로 바뀜

이 코드에서 button은 실행을 호출하는 Invoker 역할이며 기능의 변경이 필요할 때는 Lamp와 Alarm 클래스만 변경하면 되고, 기능의 추가가 필요할 때는 기존 코드의 변경 없이 새로운 Receiver와 ConcreteCommand만 추가해 주면 된다.