커맨드 패턴이란?

- 요구사항을 객체로 캡슐화해서 객체를 서로 다른 요구사항에 따라 매개변수화할 수 있다.

 

클래스 다이어그램을 살펴보자.

- Client : 커맨드 객체 생성

- Command : 어떤 Recevier를 실행할 지 연결

- Invoker : 주문을 받아서, 실행하기 위해 Command 인터페이스 연결

- Receiver : 실제 명령을 수행

 

간단한 예제를 보면서 살펴보자.

 

문제점

 집의 불을 켜주고, 차고 문을 열어주고, 스피커 전원도 켜주는 등 다양한 기능을 하는 최첨단 만능 IOT 리모컨이 존재한다. 

public class Light {
    public void on(){
        System.out.println("불을 켭니다.");
    }
    public void off(){
        System.out.println("불을 끕니다.");
    }
}

 

public class GarageDoor {
    public void open(){
        System.out.println("차고 문을 엽니다.");
    }
    public void close(){
        System.out.println("차고 문을 닫습니다.");
    }

}

 

public class Stereo {
    public void up(){
        System.out.println("볼륨을 올립니다.");
    }
    public void down(){
        System.out.println("볼륨을 내립니다.");
    }
}

사용하는 객체는 많은데 on/off, up/down 등 객체마다 사용하는 메소드가 달라 복잡하다...

 

해결책

Command 패턴을 적용해 Command 인터페이스를 추가하고 API를 일치시켜준다. 

public interface Command {
    public void execute();
    public void undo();

}

 

public class GarageDoorCommand implements Command{
    GarageDoor gd;
    public GarageDoorCommand(GarageDoor gd){
        this.gd = gd;
    }
    @Override
    public void execute(){
        gd.open();
    }

    @Override
    public void undo() {
        gd.close();
    }
}

 

public class LightCommand implements Command{
    Light light;
    public LightCommand(Light light){
        this.light = light;
    }

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

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

 

public class StereoCommand implements Command{
    Stereo stereo;

    public StereoCommand(Stereo stereo){
        this.stereo = stereo;
    }
    @Override
    public void execute() {
        stereo.up();
    }

    @Override
    public void undo() {
        stereo.down();
    }
}

 불을 켜는 것도, 스테레오의 볼륨을 조절하는 것도, 차고 문을 여는 것도 execute()라는 메소드로 일치시킬 수 있다. 

물론 클래스가 많아진다는 단점이 있지만 객체 사용에 복잡성을 제거하고 감출 수 있게 된다.

+ Recent posts