여기 보여지는 C++ code는 Motivation 섹션의 Command 크래스에 대한 대강의 구현이다. 우리는
OpenCommand,
PasteCommand 와
MacroCommand를 정의할 것이다. 먼저 추상 Commmand class 는 이렇다.
~cpp
class Command {
public:
virtual ~Command ();
virtual void Execute () = 0;
protected:
Command ();
};
~cpp
class OpenCommand : public Command {
public:
OpenCommand (Application*);
virtual void Execute ();
protected:
virtual const char* AskUser ();
private:
Application* _application;
char* _response;
};
OpenCommand::OpenCommand (Application* a) {
_application = a;
}
void OpenCommand::Execute () {
const char* name = AskUser ();
if (name != 0) {
Document* document = new Document (name);
_application->Add (document);
document->Open ();
}
}
PasteCommand 는 receiver로서 Document객체를 넘겨받아야 한다. receiver는
PasteCommand의 constructor의 parameter로서 받는다.
~cpp
class PasteCommand : public Command {
public:
PasteCommand (Document*);
virtual void Execute ();
private:
Document* _document;
};
PasteCommand::PasteCommand (Document* doc) {
_document = doc;
}
void PasteCommand::Execute () {
_document->Paste ();
}
undo 할 필요가 없고, 인자를 요구하지 않는 단순한 명령어에 대해서 우리는 command의 receiver를 parameterize하기 위해 class template를 사용할 수 있다. 우리는 그러한 명령들을 위해 template subclass인
SimpleCommand를 정의할 것이다.
SimpleCommand는 Receiver type에 의해 parameterize 되고
~cpp
template <class Receiver>
class SimpleCommand : public Command {
public:
typedef void (Receiver::* Action) ();
SimpleCommand (Receiver* r, Action a) :
_receiver (r), _action (a) { }
vitual void Execute ();
private:
Action _action;
Receiver* _receiver;
};
constructor는 receiver와 instance 변수에 대응되는 action을 저장한다. Execute는 단순히 action을 receiver에 적용한다.
~cpp
template <class Receiver>
void Simplecommand<Receiver>::Execute () {
(_receiver->*_action) ();
MyClass의 instance로 있는 Action을 호출할 command를 만들기 위해서, 클라이언트는 단순히 이렇게 코딩한다.
~cpp
MyClass* receiver = new MyClass;
// ...
Command* aCommand =
new SimpleCommand<MyClass> (receiver, &MyClass::Action);
// ...
aCommand->Execute ();
이 방법은 단지 단순한 명령어에대한 해결책일 뿐임을 명심하라. track을 유지하거나, receiver와 undo state를 argument 로 필요로 하는 좀더 복잡한 명령들은 Command의 subclass를 요구한다.
MacroCommand는 부명령어들의 sequence를 관리하고 부명령어들을 추가하거나 삭제하는 operation을 제공한다. subcommand들은 이미 그들의 receiver를 정의하므로
MacroCommand는 명시적인 receiver를 요구하지 않는다.
~cpp
class MacroCommand : public Command {
public:
MacroCommand ();
virtual ~MacroCommand ();
virtual void Add (Command*);
virtual void Remove (Command*);
virtual void Execute ();
private:
List<Command*>* _cmds;
};
MacroCommand의 열쇠는 Execute 맴버함수에 있다. 이것은 모든 부명령어들을 탐색하면서 그들 각각의 Execute operation를 수행한다.
~cpp
void MacroCommand::Execute () {
ListIterator<Command*> i (_cmds);
for (i.First (); !i.IsDone (); i.Next()) {
Command* c = i.CurrentItem ();
c->Execute ();
}
}
MacroCommand 가 Unexecute operation을 구현하기 위해서
MacroCommand의 부명령어들은 Execute operation에서 구현된 순서의 역순으로 참조되면서 unexecute해야 함을 숙지하자.
~cpp
void MacroCommand::Add (Command* c) {
_cmds->Append (c);
}
void MacroCommand::Remove (Command* c) {
_cmds->Remove (c);
}