커맨드 패턴에 대해서 이해가 가지 않는 부분이 있습니다.
글쓴이: balgarac1 / 작성시간: 화, 2014/11/04 - 8:24오후
커맨드 패턴에 대해서 우연찮게 알게되서 위키 문서 보면서 공부하고 있는데 거기서 커맨드 패턴에 대해서 이렇게 설명하고 있습니다.
커맨드 패턴에는 명령(command), 수신자(receiver), 발동자(invoker), 클라이언트(client)의 네개의 용어가 항상 따른다. 커맨드 객체는 수신자 객체를 가지고 있으며, 수신자의 메서드를 호출하고, 이에 수신자는 자신에게 정의된 메서드를 수행한다. 커맨드 객체는 별도로 발동자 객체에 전달되어 명령을 발동하게 한다. 발동자 객체는 필요에 따라 명령 발동에 대한 기록을 남길 수 있다. 한 발동자 객체에 다수의 커맨드 객체가 전달될 수 있다. 클라이언트 객체는 발동자 객체와 하나 이상의 커맨드 객체를 보유한다. 클라이언트 객체는 어느 시점에서 어떤 명령을 수행할지를 결정한다. 명령을 수행하려면, 클라이언트 객체는 발동자 객체로 커맨드 객체를 전달한다.
예로는
#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; }
제가 보았을 때는 3개의 객체 뿐인데 1개의 객체는 어떤 것인가요?? 메인에 있는 것을 클라이언트 객체라고 봐야 하나요??
Forums:
커맨드 패턴을 찾아보셨군요 :) 그런데 하고자 하는
커맨드 패턴을 찾아보셨군요 :)
그런데 하고자 하는 작업에는 패턴을 굳이 적용하실 필요는 없습니다.
패턴은 대충 이런 모양새면 해당 패턴이라고 부르는 경우도 많아서, 딱 맞아 떨어지기가 힘듭니다.
여러 패턴을 조합해서 사용하는 경우도 많구요.
일단 client의 요청을 Concrete Command 객체로 캡슐화시켜, 여기저기 던질 수 있다는 게 중요합니다.
위의 예제는 Receiver 클래스가 없고, Command 클래스들(Ingredient, Step)와 Invoker 클래스(CmdStack)만 있습니다.
Client 객체는 얘기하신 것처럼 위 예제의 경우엔 main함수 안의 내용이라고 볼 수 있겠습니다.
이 경우엔 객체의 형태는 아니지만, 만들기에 따라 main함수 안의 내용은 객체의 멤버함수 안에서 불릴 수도 있겠지요.
덧붙여, 커맨드 패턴에서 자주 거론되는 undo동작은 command가 수행하는 작업에 따라 다르지만, 대체적으로 실제 구현이 매우 까다롭습니다.
수행된 커맨드 객체의 목록을 저장하고 있으면 undo동작을 수행할 수 있는 가능성이 있다는 것이지, 패턴이 해결해 주진 않습니다.
Signature :) - "여유를 갖고 행동하되 게을러지지 말자"
네..
커맨드 패턴 적용하기에는 아직 어렵군요...
댓글 달기