본문 바로가기

디자인 패턴

디자인 패턴 - 커맨드 패턴(Command Pattern)

1. 정의

  • 요청 내역객체캡슐화해서 객체를 서로 다른 요청 내역에 따라 매개변수화 한다.

💡 요청을 큐에 저장하거나 로그로 기록하거나 작업 취소 기능을 사용할 수 있다.

2. 예시

  • 리모컨 각 버튼에 요청을 저장하여 버튼에 맞게 동작을 실행한다.

3. 그림

4. 클래스 다이어그램

5. 코드

public class Client {
    static Command lightOnCommand;
    static Command lightOffCommand;
    static Command doorOnCommand;
    static Command doorOffCommand;

    static RemoteControllerInvoker invoker;

    public static void main(String[] args){

        initSetting();

        // 조명
        invoker.pressOnButton(0);
        invoker.pressOffButton(0);

        // 문
        invoker.pressOnButton(1);
        invoker.pressOffButton(1);
    }

    private static void initSetting(){
        // 각 커맨드마다 동작할 리시버 할당
        lightOnCommand = new LightOnCommand(new LightOnReceiver());
        lightOffCommand = new LightOffCommand(new LightOffReceiver());
        doorOnCommand = new DoorOnCommand(new DoorOnReceiver());
        doorOffCommand = new DoorOffCommand(new DoorOffReceiver());

        invoker = new RemoteControllerInvoker();
        invoker.setCommand(0, lightOnCommand, lightOffCommand);
        invoker.setCommand(1, doorOnCommand, doorOffCommand);
    }
}
public interface Command {
    void execute();
}
public interface Receiver {
    void action();
}
public class LightOnReceiver implements Receiver {

    @Override
    public void action() {
        System.out.println("불이 켜졌습니다.");
    }
}
public class LightOffReceiver implements Receiver {

    @Override
    public void action() {
        System.out.println("불이 꺼졌습니다.");
    }
}
public class DoorOnReceiver implements Receiver {

    @Override
    public void action() {
        System.out.println("문이 열렸습니다.");
    }
}
public class DoorOffReceiver implements Receiver {

    @Override
    public void action() {
        System.out.println("문이 닫혔습니다.");
    }
}
public class LightOnCommand implements Command {
    Receiver light;

    public LightOnCommand(Receiver lightOn){
        this.light = lightOn;
    }

    @Override
    public void execute() {
        light.action();
    }
}
public class LightOffCommand implements Command {
    Receiver light;

    public LightOffCommand(Receiver light){
        this.light = light;
    }

    @Override
    public void execute() {
        light.action();
    }
}
public class DoorOnCommand implements Command {
    Receiver door;

    public DoorOnCommand(Receiver door){
        this.door = door;
    }

    @Override
    public void execute() {
        door.action();
    }
}
public class DoorOffCommand implements Command {
    Receiver door;

    public DoorOffCommand(Receiver door){
        this.door = door;
    }

    @Override
    public void execute() {
        door.action();
    }
}
public class RemoteControllerInvoker {
    private final int count = 2;

    Command[] onCommand;
    Command[] offCommand;

    public RemoteControllerInvoker() {
        onCommand = new Command[count];
        offCommand = new Command[count];
    }

    public void setCommand(int slot, Command on, Command off){
        this.onCommand[slot] = on;
        this.offCommand[slot] = off;
    }

    public void pressOnButton(int slot){
        this.onCommand[slot].execute();
    }

    public void pressOffButton(int slot){
        this.offCommand[slot].execute();
    }
}

https://github.com/kang-seongbeom/design_pattern

💡 Github에서 디자인 패턴 코드를 볼 수 있습니다.

6. 설명

  • Client는 요청을 Command로 캡슐화 했다.
  • Command객체 내부에 실질적 동장을 하는 Receiver가 존재한다.
  • Command는 Receiver에게 동작을 위임한다.
public class LightOnCommand implements Command {
    Receiver receiver;
    ...
    public void execute() {
        receiver.action();
    }
}
  • Invoker는 Command를 매개변수로 받고, Command 구현 클래스에게 동작을 위임한다.
// 등록
public void setCommand(int slot, Command on, Command off){
        this.onCommand[slot] = on;
}

// 위임
public void pressOnButton(int slot){
    this.onCommand[slot].execute();
}