본문 바로가기
2023년 이전/디자인 패턴

디자인 패턴 - 커맨드 패턴(Command Pattern)

by JeongUPark 2019. 11. 15.
반응형

Command 패턴이란 

실행될 기능을 캡슐화함으로써 주어진 여러 기능을 실행할 수 있는 재사용성이 높은 클래스를 설계하는 패턴을 말합니다. 즉, 이벤트가 발생했을 때 실행될 기능이 다양하면서도 변경이 필요한 경우에 이벤트를 발생시키는 클래스를 변경하지 않고 재사용하고자 할 때 유용합니다. 

그리고 커맨드 패턴에는 명령(command), 수신자(receiver), 발동자(invoker), 클라이언트(client)의 네개의 용어가 항상 따릅니다. 커맨드 객체는 수신자 객체를 가지고 있으며, 수신자의 메서드를 호출하고, 이에 수신자는 자신에게 정의된 메서드를 수행합니다. 커맨드 객체는 별도로 발동자 객체에 전달되어 명령을 발동하게 합니다. 발동자 객체는 필요에 따라 명령 발동에 대한 기록을 남길 수 있습니다. 한 발동자 객체에 다수의 커맨드 객체가 전달될 수 있습니다. 클라이언트 객체는 발동자 객체와 하나 이상의 커맨드 객체를 보유합니다. 클라이언트 객체는 어느 시점에서 어떤 명령을 수행할지를 결정합니다. 명령을 수행하려면, 클라이언트 객체는 발동자 객체로 커맨드 객체를 전달합니다.

 

정리하면 
Command
  실행될 기능에 대한 인터페이스
  실행될 기능을 execute 메서드로 선언함
ConcreteCommand
  실제로 실행되는 기능을 구현
  즉, Command라는 인터페이스를 구현함
Invoker
  기능의 실행을 요청하는 호출자 클래스
Receiver
  ConcreteCommand에서 execute 메서드를 구현할 때 필요한 클래스
  즉, ConcreteCommand의 기능을 실행하기 위해 사용하는 수신자 클래스

Client

  어느 시점에 어떤 명령을 수행할지 결정

  명령을 수행하기 위해 invoker에 command를 전달하고 수행

  

위의 패턴대로 예제를 만들어보면 

 

조선시대에 장군이 있고 장군은 2가지 명령을 합니다. 공격과 후퇴이와 관련하영 command 패턴에 맞추어 coding을 해보겠습니다.

우선 command를 만듭니다.

public interface Command {
     public abstract void excute();
}

 다음 ConcreteCommand에서 execute 메서드를 구현할 때 필요한 Reciver를 만듭니다. 

public class Sword_attack{
    public void attack() {
        System.out.println("Sword Attack");
    }
}
public class Mountain_retreat {
    public void retreat() {
        System.out.println("Retreat to Mountain");
    }
}

그리고 이에 따른 ConcreteCommand를 만듭니다.

public class Attack_command implements Command {
    private Sword_attack mAk;
    Attack_command(Sword_attack ak){
        mAk = ak;
    }
    @Override
    public void excute() {
        mAk.attack();
    }
}
public class Retreat_command implements Command {
    private Mountain_retreat mRt;
    Retreat_command(Mountain_retreat rt){
        mRt = rt;
    }
    @Override
    public void excute() {
        mRt.retreat();
    }
}

 기능의 실행을 요청하는 invoker를 만듭니다.

public class Strategy {

    private Command mA_Command;
    private Command mR_Command;
    Strategy(Command a_command,Command r_command){
        mA_Command = a_command;
        mR_Command = r_command;
    }
    public void setCommnad(Command a_command,Command r_command){
        mA_Command = a_command;
        mR_Command = r_command;
    }
    public void attack_Command(){
        mA_Command.excute();
    }
    public void retreat_Commnad(){
        mR_Command.excute();
    }

}

 

마지막으로 client를 만들어서 공격과 후퇴를 명령합니다.

public class General {

    public static void main(String[] args){
        Sword_attack s_ak = new Sword_attack();
        Attack_command a_c = new Attack_command(s_ak);
        Mountain_retreat m_rt = new Mountain_retreat();
        Retreat_command r_c = new Retreat_command(m_rt);
        Strategy g_command = new Strategy(a_c,r_c);

        g_command.attack_Command();
        g_command.retreat_Commnad();

    }
}

 이렇게 작성한 code를 실행시키면,  장군이(clinet) 전략(invoker)을 통하여 명령(command)를 내려 명령을 수행(Reciver)하게 됩니다.

 

 

 

참고

https://ko.wikipedia.org/wiki/%EC%BB%A4%EB%A7%A8%EB%93%9C_%ED%8C%A8%ED%84%B4

https://gmlwjd9405.github.io/2018/07/07/command-pattern.html

https://jusungpark.tistory.com/18?category=630296

반응형