커맨드 패턴

위키백과, 우리 모두의 백과사전.
이동: 둘러보기, 검색

커맨드 패턴(Command pattern)이란 요청을 객체의 형태로 캡슐화하여 사용자가 준 요청을 나중에 보낼 수 있도록 매서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 그리고 취소를 가능하게 만드는 패턴이다.

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

구조[편집]

Command Design Pattern Class Diagram.png

[편집]

C++[편집]

#include <iostream>
#include <vector>
#include <string>
 
using namespace std;
 
class Command{
  public:
   virtual void execute(void) =0;
   virtual ~Command(void){};
};
 
class Ingredient : public Command {
  public:
   Ingredient(string amount, string ingredient){
      _ingredient = ingredient;
      _amount = amount;
   }
   void execute(void){
      cout << " *Add " << _amount << " of " << _ingredient << endl;
   }
  private:
   string _ingredient;
   string _amount;
};
 
class Step : public Command {
  public:
   Step(string action, string time){
      _action= action;
      _time= time;
   }
   void execute(void){
      cout << " *" << _action << " for " << _time << endl;
   }
  private:
   string _time;
   string _action;
};
 
class CmdStack{
  public:
   void add(Command *c) {
      commands.push_back(c);
   }
   void createRecipe(void){
      for(vector<Command*>::size_type x=0;x<commands.size();x++){
         commands[x]->execute();
      }
   }
   void undo(void){
      if(commands.size() > 1) {
         commands.pop_back();
      }
      else {
         cout << "Can't undo" << endl;
      }
   }
  private:
   vector<Command*> commands;
};
 
int main(void) {
   CmdStack list;
 
   //Create ingredients
   Ingredient first("2 tablespoons", "vegetable oil");
   Ingredient second("3 cups", "rice");
   Ingredient third("1 bottle","Ketchup");
   Ingredient fourth("4 ounces", "peas");
   Ingredient fifth("1 teaspoon", "soy sauce");
 
   //Create Step
   Step step("Stir-fry","3-4 minutes");
 
   //Create Recipe
   cout << "Recipe for simple Fried Rice" << endl;
   list.add(&first);
   list.add(&second);
   list.add(&step);
   list.add(&third); 
   list.undo();
   list.add(&fourth);
   list.add(&fifth);
   list.createRecipe();
   cout << "Enjoy!" << endl;
   return 0;
}

자바[편집]

/*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 light=new Light();
       Command switchUp=new TurnOnLightCommand(light);
       Command switchDown=new TurnOffLightCommand(light);
 
       Switch s=new Switch(switchUp,switchDown);
 
       s.flipUp();
       s.flipDown();
   }
}