Command Pattern

개념
- 명령을 클래스로 만든다

I. 의도

     요청 자체를 객체화해 클라이언트에 패러미터로 넘길 수 있게 한다

       정의: 명령을 클래스로 만든다.
II. 활용

  • 수행할 행위 자체를 객체로 패러미터화하고자 할 때 – 절차적 프로그래밍 방식의 callback()함수와 동일
  • 서로 다른 시간에 요청을 명시하고, 저장하고, 수행할 수 있다. Command 객체는 원래의 요청과는 다른 생명주기 가짐
  • 명령어 객체 자체에 실행 취소에 필요한 상태를 저장할 수 있다
  • 변경 과정에 대한 로그를 남겨두면 시스템 고장시 원상태로 복구가 가능하다
  • 기본적인 오퍼레이션 조합으로 고난도의 오퍼레이션 구성 가능 – 트랜잭션 모델링 가능

 III. 결과

  • command는 오퍼레이션을 호출하는 객체와 오퍼레이션 수행 방법을 구현하는 객체를 분리한다
  • command 자체도 클래스로서 다른 객체와 같은 방식으로 조작되고 확장될 수 있다
  • 명령어를 조합해서 다른 명령어를 만들 수 있다 – composite 패턴을 이용해 여러 명령어 구성 가능
  • 새로운 명령어 추가가 쉽다 – 클래스 변경없이 새로운 명령어에 대한 클래스만 정의하면 된다

관련 패턴: MacroCommand를 구현하고자 할때 Composite 패턴을 사용했다. 취소를 처리할 때 객체의 상태를 관리하고자 한다면 Memento를 사용해야 한다. 또 명령어가 처리되어 처리된 이력 리스트에 저장되기 전에 명령어를 복사해야 한다면 Prototype을 사용하면 된다.

Command

오퍼레이션 수행에 필요한 인터페이스 선언

ConcreteCommand

  • Receiver 객체와 Action간 바인딩을 정의
  •  처리객체에 정의된 오퍼레이션을 호출하도록 execute()를 구현

Client

- ConcreateCommand 객체를 생성하고 그것의 receiver를 세팅함

Invoker

  • 요청(request)을 처리할 명령어를 요청(ask)

Receiver

- 요청을 처리하는데 관련된 오퍼레이션 수행방법을 알고 있음

 

소스코드

 

사례

 - 게시판의 쓰기, 삭제, 수정 등의 Action을 캡슐화

 - 그림판 프로그램에서 그리기, 지우기, 배경색 지정, 필터 적용 등을 캡슐화

 - 리모콘 기능 구현

 

/*the Invoker class*/

public class Switch {

private Command flipUpCommand;

private Command flipDownCommand;

public Switch(Command flipUpCmd,Command flipDownCmd){

this.flipUpCommand=flipUpCmd;

this.flipDownCommand=flipDownCmd;

}

public void flipUp(){

flipUpCommand.execute();

}

public void flipDown(){

flipDownCommand.execute();

}

}

/*Receiver class*/

public class Light{

public Light(){ }

public void turnOn(){

System.out.println("The light is on");

}

public void turnOff(){

System.out.println("The light is off");

}

}

/*the Command interface*/

public interface Command{

void execute();

}

/*the Command for turning on the light*/

public class TurnOnLightCommand implements Command{

private Light theLight;

public TurnOnLightCommand(Light light){

this.theLight=light;

}

public void execute(){

theLight.turnOn();

}

}

/*the Command for turning off the light*/

public class TurnOffLightCommand implements Command{

private Light theLight;

public TurnOffLightCommand(Light light){

this.theLight=light;

}

public void execute(){

theLight.turnOff();

}

}

/*The test class*/

public class TestCommand{

public static void main(String[] args){

Light l=new Light();

Command switchUp=new TurnOnLightCommand(l);

Command switchDown=new TurnOffLightCommand(l);

Switch s=new Switch(switchUp,switchDown);

s.flipUp();

s.flipDown();

}

}

  

댓글