• 작업을 요청하는 쪽과 작업을 처리하는 쪽을 분리하는 패턴
  • 요청을 처리하는 방법이 바뀌어도 호출자의 코드는 변경되지 않는다
  • 커맨드 객체 : 특정 객체에 관한 특정 작업 요청을 캡술화
  • receiver 코드가 변경되어도 invoker 코드는 바꿀 필요 없이 command만 변경하면 된다

용어

image

  • Command : 커맨드를 추상화한 인터페이스
  • Concrete Command : 구체적인 커맨드, 작업을 캡슐화하고 그 작업을 실행할 receiver를 갖고 있음
  • Receiver : 작업 처리시 어떤 일을 해야할 지 알고 있는 객체 (작업을 처리하는 객체)
  • Invoker : Command에게 특정 작업을 실행하도록 요청 (작업을 요청하는 객체)

구현

  • Receiver
public class Light {
    public void on() {
        System.out.println("---on!---");
    }

    public void off() {
        System.out.println("---off!---");
    }
}
  • Command
public interface Command {
    public void execute();
}
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();
    }
}
  • Invoker
public class Button {
    private Command command;

    public Button(Command command) {
        this.command = command;
    }

    public void press() {
        command.execute();
    }
}
  • Client
public class Main {

    public static void main(String[] args) {
        Light light = new Light();
        LightOnCommand command = new LightOnCommand(light);
        Button button = new Button(command);
        button.press();
    }
}

장점

  1. 기존 코드를 변경하지 않고 새로운 커맨드를 만들 수 있다 [OCP]
  2. 수신자 코드가 변경되어도 호출자 코드는 변경되지 않는다
  3. 커맨드 객체를 로깅, DB에 저장, 네트워크로 전송 등 다양한 방법을 활용 가능하다

단점

  1. 복잡도가 증가하고 클래스가 많아진다