Design Pattern

07. Command Pattern

kangwook 2022. 8. 22. 21:11

클라이언트가 보낸 요청을 객체로 캡슐화하여 이를 나중에 이용할 수 있도록 관리하는 패턴

Command Pattern

Command Pattern은 요청을 객체로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 메서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 취소할 수 있게하는 패턴이다.

  • Invoker : 커맨드를 저장하는 객체
  • Command : Receiver에게 동작을 수행하도록 요청하는 메서드를 가진 인터페이스
  • ConcreteCommand : Command의 여러가지 동작들을 구체적으로 구현하는 클래스
  • Receiver : 요구 사항을 수행하기 위해 어떤 일을 처리해야 하는지 알고 있는 객체

식당에서 발생하는 event로 이해하는 Command Pattern

  1. 고객이 웨이트리스에게 주문
  2. 웨이트리스는 주문서 작성 후 주방장에게 전달
  3. 주방장은 주문서를 토대로 요리
  • 웨이트리스 입장
    • 어떤 주문인지 조차도 몰라도 됨
    • 누가 식사를 준비할지 몰라도 됨
  • 주방장 입장
    • 주문서를 읽고 필요한 메뉴만 준비하면 됨
    • 누가 주문했는지 알 필요가 없음
식당 커맨드 패턴
손님 Client
웨이트리스 Invoker 객체
손님에게 주문을 받는 행위 setCommand()
주문서 Command 객체
주방장 Receiver 객체
주문을 전달하여 요리를 요청하는 행위 execute()

 


Singleton Pattern 예제

Remote Control을 이용해 전등을 키는 것

  • 리모컨의 명령을 실행시키는 커맨드를 저장할 SimpleRemoteControl
  • 여러 가지 동작들에 대한 수행을 요청하는 Command와 구체적으로 구현하는 LightCommand
  • 요구사항을 어떻게 수행하기 위해 일을 처리할 객체인 Light
  • 싱글턴 패턴을 적용시킨 코드

  • Command 클래스
    • Command 클래스는 오로지 execute() 메서드만 제공
public interface Command {
    void execute();
}
  • ConcreteCommand: LightCommand 클래스
public class LightOnCommand implements Command {
    private Light light;
 
    public LightOnCommand(Light light) {
        this.light = light;
    }
 
    public void execute() {
        light.on();
    }
}
  • Receiver : Light 클래스
public class Light {
    public void on() {
        System.out.println("turn on light");
    }
 
    public void off() {
        System.out.println("turn off light");
    }
}
  • Invoker를 이용해 Command 객체 사용 : SimpleRemoteControl 클래스
public class SimpleRemoteControl {
    private Command command;
    public void setCommand(Command command) {
        this.command = command;
    }
    public void buttonWasPressed() {
            command.execute();
    }
}
  • 이를 실행시킬 Client: RemoteControlTest 클래스
public class RemoteControlTest {
    public static void main(String[] args) {
        SimpleRemoteControl remote = new SimpleRemoteControl(); // Invoker
        Light light = new Light(); // Receiver
        LightOnCommand lightOn = new LightOnCommand(light); // Command
         
        remote.setCommand(lightOn);
        remote.buttonWasPressed();
    }
}
  • 출력 결과
Turn on light

결론

  • 실행될 기능을 캡슐화함으로써 주어진 여러 기능을 실행할 수 있는 재사용성이 높은 클래스를 설계하는 행동 패턴(Behavioral Pattern)중 하나
  • 장점
    • 요청부와 동작부를 분리시켜주기 때문에 시스템의 결합도를 낮출 수 있음
      → 각 객체들이 수정되어도 다른 객체가 영향을 받지 않음
    • Invoker와 Receiver간의 의존성을 제거
  • 단점
    • Receiver 및 Receiver의 동작이 추가된다면 그 동작에 대한 클래스를 만들어야 하기 때문에 다소 복잡해질 수 있음
    • 모든 작업이 독립적인 ConcreteCommand 클래스이므로 구현 및 유지 보수해야하는 클래스가 많음

 

 

 


본문은 Head First Design Pattern (2004) 를 참고하여 공부하고 작성하였음