Command Pattern : 공통된 커맨드를 인터페이스로 제공하며 캡슐화시켜 invoker의 입장에서 커맨드의 형태에 무관하게 구현상의 통일성을 갖게하는 패턴이다. 커맨드의 역할은 전적으로 재정의하는 클래스에 달려있기때문에 발동됬을때의 동작책임도 재정의자에 달려있다는 점을 명심해야한다. 대게 커맨드의 대상이되는 Receiver라 하는 클래스를 하위 커맨드 클래스에서 참조하며 재정의한 커맨드 인터페이스에서 이를 활용하여 원하는 행동을 하게된다.
이 패턴이 적용된 예로, Java의 Runnable이라는 인터페이스가있다. 이 인터페이스는 Thread 에서 동작가능한 클래스를 구현하게하며 run()이란 동작을 가지고있다. 여기서 Runnable은 command이고 Thread는 invoker이며 run()에서 참조되는 클래스가 Receiver가된다. Thread에서는 구현이 어떻게 되었든 Runnable의 run()만 동작시켜주면 스레드에서 해당 동작을 수행하게된다.
매크로 프로그램은 등록된 커맨드들을 순서대로 반복적으로 실행시켜준다. Command pattern을 적용하기 적합한 대상인것같다.
/* Command.java */
public interface Command {
public void execute();
}
/* Player.java */
//receiver
public class Player {
private String name;
public void move(){
System.out.println("move character");
}
public void attack(){
System.out.println("attack Monster");
}
}
/* Movement.java */
//concrete command
public class Movement implements Command {
private Player player;
public Movement(Player player){
this.player = player;
}
@Override
public void execute() {
player.move();
}
}
/* Attack.java */
//concrete command
public class Attack implements Command {
private Player player;
public Attack(Player player){
this.player = player;
}
@Override
public void execute() {
player.attack();
}
}
/* MacroPattern.java */
//invoker
public class MacroPattern {
private LinkedList<Command> cmdList;
public MacroPattern(){
cmdList = new LinkedList<Command>();
}
public void add(Command command){
cmdList.add(command);
}
public void run(){
for(Command command : cmdList){
command.execute();
}
}
}
/* main */
public static void main(String[] args){
Player player = new Player();
MacroPattern pattern = new MacroPattern();
pattern.add(new Movement(player));
pattern.add(new Attack(player));
pattern.run();
}
매크로 실행기에선 각 단계마다 어떤동작을 하는지 알지못한다. 다만 때에맞춰 실행명령을 내려줄 뿐이다.(Invoker)
움직임, 공격, 줍기 등 각 커맨드는 명령을 구체화한다.(Concrete command)
플레이어는 자신의 동작을 정의할 뿐 실재 수행명령은 concrete command class로부터 불려지게된다.(Receiver)
매크로 동작을 추가할 필요가 있다 해도 다른 어떤 클래스에도 영향을 미치지않는다. 커맨드의 실행을 일반화 시켰기 때문에 커맨드의 종류와 Invoker와의 결합도가 제로에 가깝다. 그만큼 유연하여 확장성이 강하다고 할 수 있다. 커맨드의 타입에 따라 switch-case구조로 설계하였다면 절대로 가질 수 없는 이점이다.
'Coding Note' 카테고리의 다른 글
[Design pattern] Adapter (0) | 2013.02.20 |
---|---|
[Design pattern] Iterator (0) | 2013.02.04 |
[Design pattern] Chain of Responsibliity (1) | 2013.02.02 |
[Design pattern] Prototype (1) | 2013.02.01 |
[Design pattern] Builder (0) | 2013.01.31 |