[디자인패턴 수업 11주차 1차시] Command Pattern - 홈시어터 다중 버튼 리모콘(인보커) 예시

Jin Hur·2021년 11월 15일
0
post-custom-banner

정의

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

커멘드 객체

일련의 행동을 특정 리시버하고 연결시킴으로써 요구 사항을 캡슐화한 것. 행동과 리시버를 한 객체(커멘드 객체)에 집어넣고, execute()라는 메서드 하나만 외부에 공개하는 방법을 쓴다. 외부에서 볼 땐 어떤 객체가 리시버 역할을 하는지, 그 리시버에서 실제로 어떤 일을 수행하는 지 알 수 없다. 그저 execute() 메서드를 호출하면 요구 사항이 처리된다는 것만 알 수 있을 뿐.

구체적인 클래스 다이어그램

1. 클라이언트는 ConcreteCommand를 생성하고 리시버를 설정한다.
2. 리시버는 요구 사항을 수행하기 위해 어떤 일을 처리해야 하는지 알고 있는 객체이다.
3. ConcreteCommand는 특정 행동과 리시버 사이를 연결해준다. 인보커에서 execute()가 호출되면, 이 객체에서 리시버에 있는 메서드(action())을 호출함으로써 작업을 처리한다.
4. 인보커에는 명령이 들어있으며, execute() 메서드를 호출함으로써 커멘드 객체에게 특정 작업을 수행해 달라는 요구를 하게 됨.



슬롯에 명령 할당하기(인보커 코드)

리모컨(인보커, Invoker)에 여러 슬롯이 있다치면, 각 슬롯에 명령을 할당할 수 있다. 사용자가 버튼을 누르면 그 버튼에 상응하는 커멘드 객체의 execute() 메서드가 호출되고, 리시버(전등, 선풍기, 오디오 등)에서 특정 행동을 하는 메서드가 실행된다. 결국 이 리모컨은 여러 장치들을 조작할 수 있는 만능 리모컨인 셈이다.

public class RemoteControl {
    // 하나 이상의 명령을 담을 수 있다.
    Command[] onCommands;   // on 계열 명령들
    Command[] offCommands;  // off 계열 명령들
    
    public RemoteControl(){
        onCommands = new Command[7];
        offCommands = new Command[7];
        
        // 일종의 널 객체로 초기화
        Command noCommand = new NoCommand();
        for(int i=0; i<7; i++){
            onCommands[i] = noCommand[];
            offCommands[i] = noCommand[];
        }
    }

    // 명령을 등록할 때 사용하는 setCommand 메서드
    public void setCommand(int slot, Command onCommand, Command offCommand){
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
    
    public void onButtonPushed(int slot){
        onCommands[slot].execute();
    }
    public void offButtonPushed(int slot){
        offCommands[slot].execute();
    }
}

위 리모컨 코드에서 볼 수 있듯이,
일곱개의 on, off 명령을 처리할 수 있고, 각 명령은 배열에 저장된다.
생성자는 각 on, off 배열의 인스턴스를 만들고 초기화하기만 하면된다.

사용자가 on 또는 off 버튼을 누르면 리모컨 하드웨어에서 각 버튼에 대응되는 onButtonPushed() 또는 offButtonWasPushed() 메서드를 호출한다.

NoCommand는 일종의 널 객체

public class NoCommand implements Command{
    @Override
    public void execute() {
        // nothing
    }
}

리시버 예시
Stereo 리시버

public class Stereo { 
    public void on(){
        System.out.println("Stereo On");
    }
    public void off(){
        System.out.println("Stereo Off");
    }
    public void setCd(){}
    public void setDvd(){}
    public void setRadio(){}
    public void setVolume(){}   
}
post-custom-banner

0개의 댓글