커맨드 패턴

이정석·2023년 6월 23일
0

디자인패턴

목록 보기
21/23

커맨드 패턴이란?

요청 자체를 객체로 만들어 실행될 기능을 캡슐화해 연산을 요청하는 객체와 수행하는 객체를 분리시켜 결합도를 낮추는 패턴이다.


문제상황

1. 전등을 나타내는 Light 클래스가 있다 하자.

public class Light {
    public void on() {
        System.out.println("Light On");
    }

    public void off() {
        System.out.println("Light Off");
    }
}

2. Light를 키고 끄기위한 Client는 다음과 같다.

public class Client {
    public static void main(String[] args) {
        Light light = new Light();
        light.on();
        light.off();
    }
}

위 상황에서 Client는 Light의 on, off를 직접 호출한다. 이런 경우는 Client와 Light간의 강한 결합이 발생되어 Light의 새로운 기능이나 기능변경이 이뤄질 때 Client의 코드를 수정해야 할수도 있다.

실행될 기능(Command)을 캡슐화해 Client와 Light사이의 의존성을 제거하자


구조

  1. Invoker: Command를 사용하는 객체로 명령을 수행하도록 요청하는 클래스이다.
  2. Command: 명령을 수행할 인터페이스를 정의한 것으로 실행될 기능을 execute 메서드로 정의하였다.
  3. ConcreteCommand: Command를 구현하는 클래스로 실제로 수행할 기능을 구현한다. Receiver 객체와 연결되어 있다.
  4. Receiver: 실제로 명령을 수행하는 클래스로 ConcreteCommand가 명령을 수행할 때, Receiver의 메서드를 호출해 작업을 수행한다.

코드(JAVA)

1. Command

public interface Command {
    void execute();
}

구조의 Command에 해당하는 인터페이스로 execute를 정의한다.

2. LightOn, LightOff Command

public class LightOnCommand implements Command {
    private Light light;

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

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

public class LightOffCommand implements Command {
    private Light light;

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

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

ConcreteCommand에 해당하는 클래스로 Receiver에 해당하는 Light에 명령(on,off)를 수행하도록 하는 클래스이다.

3. Light

public class Light {
    public void on() {
        System.out.println("The light is on");
    }

    public void off() {
        System.out.println("The light is off");
    }
}

Receiver에 해당하는 클래스로 실제 on, off 기능을 수행한다.

4. RemoteControl

public class RemoteControl {
    private Command command;

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

    public void pressButton() {
        command.execute();
    }
}

Invoker에 하는 RemoteControl이다. 설정된 pressButton으로 Command에 기능을 요청한다.

5. Client

public class Client {
    public static void main(String[] args) {
        Light light = new Light();
        Command lightOn = new LightOnCommand(light);
        Command lightOff = new LightOffCommand(light);
        
        RemoteControl control = new RemoteControl();

        control.setCommand(lightOn);
        control.pressButton();
        control.setCommand(lightOff);
        control.pressButton();
    }
}

커맨드 패턴이 적용된 Client로 Light가 변경거나 새로운 기능이 추가되어도 Client가 받는 영향이 적다. 즉, 기존의 코드 변경없이 command가 추가가능하다.


MacroCommand

MacroCommand는 여러개의 커맨드를 한번에 실행할 수 있도록 하는 Command로 Command를 상속받으며 Command의 List를 가지고 있다.

public class MacroCommand implements Command {
    private List<Command> commands;

    public MacroCommand(List<Command> commands) {
        this.commands = commands;
    }

    @Override
    public void execute() {
        for (Command command : commands) {
            command.execute();
        }
    }
}
profile
게임 개발자가 되고 싶은 한 소?년

0개의 댓글