영어로 이해하는 연습을 하자..
이것도 다 수련..
http://en.wikipedia.org/wiki/Command_pattern
객체지향프로그래밍에서 커맨드 패턴은 객체가 메소드를 부를때 필요한 정보를 캡슐화하여 나타내는 디자인 패턴이다.
객체는 메소드와 메소드 파라미터의 값을 갖는다.
커맨드 패턴은 client, invoker, receiver 3가지가 연관되어 있다. 클라이언트(client)는 커맨드 객체를 사용하고, 이후 메소드를 부를때 사용되는 정보를 제공한다. 인보커(호출자, invoke:부르다는 의미)는 메소드가 불릴때 결정된다. 리시버는 메소드 코드가 포함된 클래스의 인스턴스다.
커맨드 패턴을 만들면 위임, 순차나 메소드 실행이 필요한 공통 컴포넌트를 쉽게 만들수 있다. 이때 해당 메소드의 주인이나, 메소드 파라미터를 알 필요가 없다.
사용
Undo
사용자 액션은 스택에 쌓게 되고 그것을 꺼내면 undo가 된다.
트랜잭셔널 행위
롤백이나 자동으로 수행되다 실패했을때 undo는 필수로 있어야 하는데 커맨드 오브젝트는 two-phase commit 을 구현하는데 사용된다.
프로그래스 바
순차적으로 선택된 커맨드들을 실행시키는 프로그램이 있을때, 커맨드에 getEstimateDuration() 메소드를 정의하면 이것을 사용해 프로그래스 바에 반영할 수 있다.
위저드 (마법사)
GUI프로그램에서 "Finish" 를 선택했을때 자동으로 실행되는 프로그램을 만드는데 사용된다.
GUI 버튼, 메뉴 아이템
Swing에서 Action이 커맨드 객체이다.
쓰레드 풀
보통 쓰레드 풀이 가지고 있는 addTask() 메소드를 가지고 있는데 큐에 task를 더하는 방식으로 되어 있다. 큐에 있는 아이템들이 커맨드 객체.
매크로
사용자 액션이 커맨드 객체로 되어 있다면 이것을 기억해서 같은 액션을 수행할 수 있게 된다.
네트워크
컴퓨터 네트워크 게임처럼 입력한 커맨드를 네트워크를 통해 다른 머신에서 실행시킨다.
병렬 프로세싱
커맨드들이 자원을 공유하고 많은 쓰레드를 병렬적으로 실행하기 위해 쓰인다.
구조
예제
/*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 FlipUpCommand implements Command{
private Light theLight;
public FlipUpCommand(Light light){
this.theLight=light;
}
public void execute(){
theLight.turnOn();
}
}
/*the Command for turning off the light*/
public class FlipDownCommand implements Command{
private Light theLight;
public FlipDownCommand(Light light){
this.theLight=light;
}
public void execute(){
theLight.turnOff();
}
}
/*The test class or client*/
public class PressSwitch{
public static void main(String[] args){
Light lamp = new Light();
Command switchUp=new FlipUpCommand(lamp );
Command switchDown=new FlipDownCommand(lamp );
Switch s=new Switch(switchUp,switchDown);
try {
if (args[0].equalsIgnoreCase("ON")){
s.flipUp();
System.exit(0);
}
if (args[0].equalsIgnoreCase("OFF")){
s.flipDown();
System.exit(0);
}
System.out.println("Argument \"ON\" or \"OFF\" is required.");
} catch (Exception e){
System.out.println("Argument's required.");
}
}
}

예제에서 보여준 심플 스위치는 불을 키고 끄는 두가지 커맨드가 있다. 커맨드 패턴을 사용하면서 얻게 되는 장점은 스위치를 꼭 불을 끄고 키는데 사용하는게 아니라 엔진(engine)을 키고 끄는 것처럼 다른 것에도 적용할 수 있다는 것이다.
Command : Command.java
ConcreteCommand : FlipDownCommand.java, FilpUpCommand.java
Receiver : Light.java
Invoker : Switch.java
Client : PressSwitch.java
더보기
command pattern은 전구 스위치를 생각하면 된다. 사용자는 불을 키고 끌때 내부적으로 어떻게 돌아가는지 관심이 없다. 단지 스위치를 올리면 불이켜지고 내리면 불이 꺼지면 된다.
커맨드 패턴은 우리가 스위치를 올리면 불이켜지고, 내리면 불이꺼진다는 당연한 것을 패턴으로 프로그래밍에 적용한 것이다.
커맨드 패턴을 통해 요청에 필요한 정보들을 객체로 숨긴다.
커맨드 패턴 구조는 커맨드, 인보커, 리시버, 클라이언트로 크게 나뉜다.
인보커는 사용자에게 보여지는 요청부분이다. 인보크가 나타내다란 뜻이라는걸 생각해 보면 이해가 쉬울것 같다.
스위치로 올리는 요청, 내리는 요청을 실행한다. 이것이 인보커다.
다음은 커맨드. 내리고 올리는 요청을 말한다. 커맨드는 인터페이스다. 실제 커맨드 구현은 콘크리트 커맨드에서 구현이 된다.
인보커는 커맨드의 excute 메소드를 실행시킨다.
리시버는 명령으로 변화가 일어나는 것을 말한다. 전구가 리시버로 커맨드로 부터 요청을 받아 불이 끄고, 켠다.
클라이언트는 콘크리트 커맨드를 생성하고 리시버를 설정한다.
예제를 보며 확인을 하면 Switch 클래스는 인보커로 커맨드를 설정하고 클라이언트로 부터 명령이 들어오면 커맨드를 실행시킨다.
Command는 인터페이스로 excute 메소드를 가지고 있다. FlipUp/DownCommand 클래스는 Command 인터페이스를 구한 것으로 리시버를 설정하고 excute 메소드에서 리시버의 action을 실행한다.
Light 클래스는 리시버로 최종 타겟이 되고 action을 가지고 있다. 여기서 action은 turnOn과 turnOff다
PressSwitch는 클라이언트로 커맨들를 생성하고 리시버를 설정한다. 또한 인보커를 실행시켜 프로그램을 수행하도록 한다.
이렇게 요청을 객체화 함으로써 한번 더 추상화를 할 수 있다. 이렇게 추상화된 객체를 이용해 undo, 트랜젝션, 위저드(마법사) 등을 쉽게 구현할 수 있다.