Command Pattern

YeJI Kang·2021년 6월 6일
0

Head First Design Pattern

목록 보기
6/14

커맨드 패턴(Command Pattern) 예시

커맨드 객체는 일련의 행동을 특정 리시버하고 연결시킴으로써 요구 사항을 캡슐화합니다.

아래 샘플 코드에서 SimpleRemoteControl 은 인보커(Invoker) 클래스, LightOnCommnad 클래스는 커맨드(Command) 클래스, Light 는 리시버(Receiver) 클래스, RemoteControlTest 는 클라이언트(Client) 클래스의 예시입니다.

reference code

SimpleRemoteControl.java (Invoker)

SimpleRemoteControlCommand 객체를 들고 있습니다. 그리고 실제 Command 객체가 어떤 객체인지, 어떤 일을 하는지 상관없이 버튼이 눌리면 execute 함수를 호출합니다.

public class SimpleRemoteControl {
    Command slot;

    public SimpleRemoteControl() { }

    public void setCommand(Command command) {
        this.slot = command;
    }

    public void buttonWasPressed() {
        slot.execute();
    }
}

Command.java

public interface Command {
    void execute();
}

LightOnCommand.java (Command)

LightOnCommand 는 리시버(Receiver)객체를 참조하고 있습니다. 이 리시버는 Client로부터 주입받은 리시버입니다.

public class LightOnCommand implements Command {

    Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}

RemoteControlTest.java (Client)

클라이언트(Client)는 커맨드 객체와 리시버 객체를 모두 들고 있고 커맨드 객체에 리시버 객체를 주입하여 줍니다. 그래서 커맨드 객체에서 exexcute 함수가 불리게 되면 주입된 리시버 객체에서 어떤 특정 일을 수행하게 됩니다.

public class RemoteControlTest {

    public static void main(String[] args) {
        SimpleRemoteControl remote = new SimpleRemoteControl();
        Light light = new Light();
        LightOnCommand lightOn = new LightOnCommand(light);

        remote.setCommand(lightOn);
        remote.buttonWasPressed();

        Garage garage = new Garage();
        GarageDoorOpenCommand garageDoorOpen = new GarageDoorOpenCommand(garage);

        remote.setCommand(garageDoorOpen);
        remote.buttonWasPressed();
    }
}

커맨드 패턴(Command Pattern)의 정의

Head First Design Patterns에서 정의한 커맨드 패턴의 정의는 아래와 같습니다.

커맨드 패턴(Command Pattern)
커맨드 패턴을 이용하면서 요구 사항을 객체로 캡슐화할 수 있으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수도 있습니다. 또한 요청 내역을 큐에 저장하거나 로그로 기록할 수도 있으며, 작업 취소 기능도 지원 가능합니다.

커맨드 패턴(Command Pattern)의 활용

요청을 큐에 저장하기

커맨드 객체를 사용하면 컴퓨테이션(computation)의 한 부분을 패키지(리시버와 일련의 행동)로 묶어서 객체 형태로 전달한느 것도 가능합니다. 이를 통해서 스케줄러, 스레드 풀, 작업 큐와 같은 곳에 활용될 수 있습니다.

작업 큐를 보면 어떤 업무를 수행하는지 모른채 큐에 커맨드 객체를 쌓습니다. 그리고 순차적으로 커맨드를 가져오고 커맨드가 어떤 업무를 수행하든지 상관없이 커맨드 객체의 execute 만 호출합니다.

요청을 로그에 기록하기

애플리케이션이 다운되었을 때에 이전 기록을 복구하는 기능을 추가할 수 있습니다. Command 인터페이스에 store()load() 를 추가하면 매번 execute() 가 불릴 때 store() 을 수행합니다. 그러면 애플리케이션이 다운되면 load() 를 통해 복구할 수 있습니다.

하지만, 방대한 자료구조인 애플리케이션의 경우, store() 라는 함수의 오버헤드가 커지게 됩니다. 이러한 경우에는 요청을 로그에 기록합니다. 그리고 애플리케이션이 다운되었을 경우, 로그를 통해 시스템을 복구시키는 데에 활용할 수 있습니다.

profile
재밌는 것만 하고 싶어 ʕ•ﻌ•ʔ

0개의 댓글