1.1. Intent ¶
request λ₯Ό κ°μ²΄λ‘ μΊ‘μν μν΄μΌλ‘μ λ€λ₯Έ requestλ€μ κ°μ§ ν΄λΌμ΄μΈνΈλ₯Ό μΈμνμν€κ±°λ, requestλ₯Ό queueνκ±°λ λκΈ°μν€λ©°, undoκ° κ°λ₯ν λͺ
λ Ήμ μ§μνλ€.
1.3. Motivation ¶
λλλ‘ μμ²λ°μ λͺ
λ Ήμ΄λ requestλ₯Ό λ°λ κ°μ²΄μ λν μ 보μμ΄ κ°μ²΄λ€μκ² requestλ₯Ό λκ²¨μ€ λκ° μλ€. μλ₯Ό λ€μ΄ user interface tookitμ buttonμ΄λ menuμ²λΌ μ¬μ©μ μ
λ ₯μ λν΄ μλ΅νκΈ° μν΄ μμ²μ μ²λ¦¬νλ κ°μ²΄λ€μ ν¬ν¨νλ€. νμ§λ§, μ€μ§ toolkitμ μ¬μ©νλ μ΄ν리μΌμ΄μ
λ§μ΄ μ΄λ€ κ°μ²΄κ° μ΄λ€μΌμ ν΄μΌ ν μ§ μκ³ μμΌλ―λ‘, toolkitμ buttonμ΄λ menuμ λν΄μ μμ²μ λν΄ λͺ
μμ μΌλ‘ ꡬνμ ν μ μλ€. toolkit λμμ΄λλ‘μ μ°λ¦¬λ requestλ₯Ό λ°λ κ°μ²΄λ requestλ₯Ό μ²λ¦¬ν operationsμ λν΄ μμ§ λͺ»νλ€.
Command Patternμ request λ₯Ό κ°μ²΄νν¨μΌλ‘μ toolkit κ°μ²΄λ‘ νμ¬κΈ λΆνΉμ ν μ΄ν리μΌμ΄μ
κ°μ²΄μ λν requestλ₯Ό λ§λ€κ² νλ€. μ΄ κ°μ²΄λ λ€λ₯Έ κ°μ²΄μ²λΌ μ μ₯λ μ μμΌλ©° pass around κ°λ₯νλ€. μ΄ patternμ keyλ μνν λͺ
λ Ήμ΄μ λν μΈν°νμ΄μ€λ₯Ό μ μΈνλ μΆμ Command classμ μλ€. μ΄ μΈν°νμ΄μ€μ κ°μ₯ λ¨μν ννμμλ μΆμμ μΈ Execute operationμ ν¬ν¨νλ€. ꡬ체νλ Command subclassλ€μ requestμ λν receiverλ₯Ό instance λ³μλ‘ μ μ₯νκ³ requestλ₯Ό invokeνκΈ° μν Execute operationμ ꡬνν¨μΌλ‘μ receiver-action μ§μ ꡬ체νμν¨λ€. The receiver has the knowledge required to carry out the request.
Menuλ μ½κ² Command Objectλ‘ κ΅¬νλ μ μλ€. Menu μ κ°κ°μ μ νμ κ°κ° MenuItem ν΄λμ€μ μΈμ€ν΄μ€μ΄λ€. Application ν΄λμ€λ μ΄ λ©λ΄λ€κ³Ό λλ¨Έμ§ μ μ μΈν°νμ΄μ€μ λ°λΌμ λ©λ΄μμ΄ν
μ ꡬμ±νλ€. Application ν΄λμ€λ μ μ κ° μ΄ Document κ°μ²΄μ trackμ μ μ§νλ€.
μ΄ν리μΌμ΄μ
μ κ°κ°μ ꡬ체μ μΈ Command μ subclassλ€λ‘ κ°κ°κ°MenuItem κ°μ²΄λ₯Ό μ€μ νλ€. μ¬μ©μκ° MenuItemμ μ ννμλ MenuItemμ λ©λ΄μμ΄ν
μ ν΄λΉ λͺ
λ ΉμΌλ‘μ Execute oerationμ νΈμΆνκ³ , Executeλ μ€μ μ λͺ
λ Ήμ μννλ€. MenuItemκ°μ²΄λ€μ μμ λ€μ΄ μ¬μ©ν Commandμ subclassμ λν μ 보λ₯Ό κ°μ§κ³ μμ§ μλ€. Command subclassλ ν΄λΉ requestμ λν receiverλ₯Ό μ μ₯νκ³ , receiverμ νλλ κ·Έ μ΄μμ λͺ
λ Ήμ΄λ€μ invokeνλ€.
μλ₯Ό λ€μ΄ PasteCommandλ clipboardμ μλ textλ₯Ό Documentμ λΆμ΄λ κΈ°λ₯μ μ§μνλ€. PasteCommand μ receiverλ μΈμ€ν΄μ€νν λ μ€μ λμ΄μλ Docuemntκ°μ²΄μ΄λ€. Execute λͺ
λ Ήμ ν΄λΉ λͺ
λ Ήμ receiverμΈ Documentμ Paste operation μ invoke νλ€.
OpenCommandμ Execute operationμ λ€λ₯΄λ€. OpenCommandλ μ¬μ©μμκ² λ¬Έμ μ΄λ¦μ λ¬Όμλ€, λμνλ Document κ°μ²΄λ₯Ό λ§λ€κ³ , ν΄λΉ λ¬Έμλ₯Ό μ¬λ μ΄ν리μΌμ΄μ
μ λ¬Έμλ₯Ό μΆκ°ν λ€ (MDIλ₯Ό μκ°ν κ²) λ¬Έμλ₯Ό μ°λ€.
λλλ‘ MenuItemμ μ°μλ λͺ
λ Ήμ΄λ€μ μΌκ΄μνμ νμλ‘ νλ€. μλ₯Ό λ€μ΄μ ν΄λΉ νμ΄μ§λ₯Ό μ€μμ λκ³ μΌλ°ν¬κΈ°ν μν€λ MenuItemμ CenterDocumentCommand κ°μ²΄μ NormalSizeCommand κ°μ²΄λ‘ λ§λ€ μ μλ€. μ΄λ¬ν λ°©μμΌλ‘ λͺ
λ Ήμ΄λ€μ μ΄μ΄μ§κ² νλ κ²μ μΌλ°μ μ΄λ―λ‘, μ°λ¦¬λ 볡μλͺ
λ Ήμ μννκΈ° μν MenuItemμ νμ©νκΈ° μν΄ MacroCommandλ₯Ό μ μν μ μλ€. MacroCommandλ λ¨μν λͺ
λ Ήμ΄λ€μ sequenceλ₯Ό μννλ Command subclassμ ꡬ체νμ΄λ€. MacroCommandλ MacroCommandλ₯Ό μ΄λ£¨κ³ μλ commandλ€μ΄ κ·Έλ€μ receiverλ₯Ό μ μνλ―λ‘ λͺ
μμ μΈ receiverλ₯Ό κ°μ§μ§ μλλ€.
μ΄λ¬ν μλ€μμ, μ΄λ»κ² Command patternμ΄ ν΄λΉ λͺ
λ Ήμ invokeνλ κ°μ²΄μ λͺ
λ Ήμ μννλ μ 보λ₯Ό κ°μ§ κ°μ²΄λ₯Ό λΆλ¦¬νλμ§ μ£Όλͺ©νλΌ. μ΄λ¬ν¨μ μ μ μΈν°νμ΄μ€λ₯Ό λμμΈν¨μ μμ΄μ λ§μ μ μ°μ±μ μ 곡νλ€. μ΄ν리μΌμ΄μ
μ λ¨μ§ menuμ push buttonμ΄ κ°μ ꡬ체μ μΈ Command subclassμ μΈμ€ν΄μ€λ₯Ό 곡μ ν¨μΌλ‘μ menu μ push button μΈν°νμ΄μ€ μ 곡ν μ μλ€. μ°λ¦¬λ λμ μΌλ‘ commandλ₯Ό λ°κΏ μ μμΌλ©°, μ΄λ¬ν¨μ context-sensitive menu λ₯Ό ꡬννλλ° μ μ©νλ€. λν μ°λ¦¬λ λͺ
λ Ήμ΄λ€μ 컀λ€λ λͺ
λ Ήμ΄μ νλλ‘ μ‘°ν©ν¨μΌλ‘μ command scriptingμ μ§μν μ μλ€. μ΄λ¬ν λͺ¨λ κ²μ requestλ₯Ό issueνλ κ°μ²΄κ° μ€μ§ μ΄λ»κ² issueν νλμ§λ§ μκ³ μμΌλ©΄ λκΈ°λλ¬Έμ κ°λ₯νλ€. requestλ₯Ό λνλ΄λ κ°μ²΄λ μ΄λ»κ² requestκ° μνλμ΄μΌ ν μ§ μ νμκ° μλ€.
1.4. Applicability ¶
λ€μκ³Ό κ°μ κ²½μ°μ CommandPatternμ μ΄μ©νλΌ.
- MenuItem κ°μ²΄κ° νλ €λ μΌμ λμ΄μ μννλ €λ actionμ μν΄ κ°μ²΄λ₯Όμ μΈμνμν¬λ. νλ‘κ·Έλλ¨Έλ procedural languageμμμ callback ν¨μμ²λΌ μΈμνμν¬ μ μλ€. Commandλ callbackν¨μμ λν κ°μ²΄μ§ν₯μ μΈ λμμ΄λ€.
- λ€λ₯Έ μκ°λμ requestλ₯Ό ꡬ체ννκ±°λ queueνκ±°λ μννκΈ° μν λ. Command κ°μ²΄λ requestμ λ
립μ μΈ lifetimeμ κ°μ§ μ μλ€. λ§μΌ requestμ receiverκ° κ³΅κ° λ
립μ μΈ λ°©λ²μΌλ‘ (λ€νΈμν¬ λ±) μ£Όμλ₯Ό ννν μ μλ€λ©΄ νλ‘κ·Έλλ¨Έλ requestμ λν Command κ°μ²΄λ₯Ό λ€λ₯Έ νλ‘μΈμ€μκ² μ λ¬νμ¬ μ²λ¦¬ν μ μλ€.
- undo κΈ°λ₯μ μ§μνκΈ° μν λ. Commandμ Execute operationμ ν΄λΉ Commandμ ν¨κ³Όλ₯Ό λλ리기 μν stateλ₯Ό μ μ₯ν μ μλ€. Command λ Execute μνμ ν¨κ³Όλ₯Ό λλ리기 μν Unexecute operationμ μΈν°νμ΄μ€λ‘μ μΆκ°ν΄μΌ νλ€. μνλ commandλ history listμ μ μ₯λλ€. history listλ₯Ό μ λ€λ‘ κ²μνλ©΄μ Unexecuteμ Executeλ₯Ό λΆλ¦μΌλ‘μ 무μ νμ undoκΈ°λ₯κ³Ό redoκΈ°λ₯μ μ§μν μ μκ² λλ€.
- logging changeλ₯Ό μ§μνκΈ° μν λ. logging change λ₯Ό μ§μν¨μΌλ‘μ μμ€ν
μΆ©λμ΄ λ κ²½μ°μ λν΄ ν΄λΉ commandλ₯Ό μ¬μλ ν μ μλ€. Command κ°μ²΄μ load μ store operationμ μΆκ°ν¨μΌλ‘μ changeμ logλ₯Ό μ μ§ν μ μλ€. crashλ‘λΆν° 볡ꡬνλ κ²μ λμ€ν¬λ‘λΆν° logged commandλ₯Ό μ½μ΄λ€μ΄κ³ Execute operationμ μ¬μ€ννλ κ²μ μ€μν λΆλΆμ΄λ€.
- κΈ°λ³Έλͺ
λ Ήμ΄λ€λ₯Ό κΈ°λ°μΌλ‘ μ΄μ©ν νμ΄λ 벨μ λͺ
λ Ήλ€λ‘ μμ€ν
μ μ‘°μ§ν λ. κ·Έλ¬ν¨ μ‘°μ§μ transactionμ μ§μνλ μ 보μμ€ν
μμ 보νΈνλ λ°©μμ΄λ€. transactionμ λ°μ΄ν°μ λ³νμ μ§ν©μ μΊ‘μννλ€. CommandPatternμ transactionμ λμμΈνλ νλμ λ°©λ²μ μ 곡νλ€. Commandλ€μ 곡ν΅λ μΈν°νμ΄μ€λ₯Ό κ°μ§λ©°, λͺ¨λ transactionλ₯Ό κ°μ λ°©λ²μΌλ‘ invokeν μ μλλ‘ νλ€. CommandPatternμ λν μλ‘μ΄ transactionλ€μ μμ€ν
μ νμ₯μν€κΈ° μ½κ² νλ€.
1.6. Participants ¶
- Command
- μνν operationμ μν μΈν°νμ΄μ€λ₯Ό μ μΈνλ€.
- ConcreteCommand (PasteCommand, OpenCommand)
- Receiver κ°μ²΄μ action λ¬Άμμ μ μνλ€.
- Client (Application)
- ConcreteCommand κ°μ²΄λ₯Ό λ§λ€κ³ receiverλ‘ μ νλ€.
- Invoker (MenuItem)
- command μκ² requestλ₯Ό μννλλ‘ μμ²νλ€.
- Receiver (Document, Application)
- μ²λ¦¬ν requestμ λν΄ λͺ λ Ήμ΄λ€μ μ΄λ»κ² μνν΄μΌ ν μ§ μκ³ μλ€. μ΄λ ν ν΄λμ€λ μ§ Receiverλ‘μ νλκ°λ₯νλ€.
1.7. Collaborations ¶
- clientλ ConcreteCommand κ°μ²΄λ₯Ό λ§λ€κ³ , receiverλ₯Ό μ νλ€.
- Invoker κ°μ²΄λ ConcreteCommandκ°μ²΄λ₯Ό μ μ₯νλ€.
- invokerλ commandμμ Executeλ₯Ό νΈμΆν¨μΌλ‘μ requestλ₯Ό issueνλ€. λͺ
λ Ήμ΄κ° undoκ°λ₯ν λ, ConcreteCommandλ λͺ
λ Ήμ΄λ₯Ό undoνκΈ° μν stateλ₯Ό μ μ₯νλ€.
- ConcreteCommand κ°μ²΄λ requestλ₯Ό μ²λ¦¬νκΈ° μν΄ receiverμμ operationμ invokeνλ€.
1.8. Consequences ¶
CommandPatternμ λ€μκ³Ό κ°μ κ²°κ³Όλ₯Ό κ°μ Έμ¨λ€.
- Commandλ ν΄λΉ κ°μ²΄μ λͺ
λ Ήμ invokeνλ κ°μ²΄μ μ΄λ»κ² μνν΄μΌ ν μ§ μκ³ μλ κ°μ²΄μμ κ²°ν©μ ν΄μ νλ€.
- Commandλ 첫λ²μ§Έλ¨κ³μ ν΄λμ€ κ°μ²΄μ΄λ€. Commandλ μ‘°μλμ΄μ§ μ μμΌλ©΄μ λ€λ₯Έ κ°μ²΄λ€κ³Ό λ§μ°¬κ°μ§λ‘ νμ₯κ°λ₯νλ€.
- Commandλ₯Ό λ¬Άμ μ μλ€. μμ μ€λͺ
ν MacroCommandκ° κ·Έ μκ° λλ€. μΌλ°μ μΌλ‘ composite commandλ€μ CompositePatternμ μΈμ€ν΄μ€μ΄λ€.
- μλ‘μ΄ Commandλ₯Ό μΆκ°νκΈ°κ° μ½λ€. μλνλ©΄ μ΄λ―Έ μ‘΄μ¬νκ³ μλ ν΄λμ€λ€μ κ³ μΉ νμκ° μκΈ° λλ¬Έμ΄λ€.
1.10. Sample Code ¶
μ¬κΈ° 보μ¬μ§λ C++ codeλ Motivation μΉμ
μ Command ν¬λμ€μ λν λκ°μ ꡬνμ΄λ€. μ°λ¦¬λ OpenCommand, PasteCommand μ MacroCommandλ₯Ό μ μν κ²μ΄λ€. λ¨Όμ μΆμ Commmand class λ μ΄λ λ€.
~cpp class Command { public: virtual ~Command (); virtual void Execute () = 0; protected: Command (); };
OpenCommandλ μ μ λ‘λΆν° μ 곡λ μ΄λ¦μ λ¬Έμλ₯Ό μ°λ€. OpenCommandλ λ°λμ Constructorμ Application κ°μ²΄λ₯Ό λ겨λ°μμΌ νλ€. AskUser λ μ μ μκ² μ΄μ΄μΌ ν λ¬Έμμ μ΄λ¦μ 묻λ 루ν΄μ ꡬννλ€.
~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ν΄μΌ ν¨μ μμ§νμ.
μ΅μ’
μ μΌλ‘ MacroCommand λ λΆλͺ
λ Ήμ΄λ€μ κ΄λ¦¬ν operationμ μ 곡ν΄μΌνλ€. MacroCommandλ λν MacroCommandλ₯Ό μ΄λ£¨λ λΆλͺ
λ Ήμ΄λ€μ μμ ν μ±
μμ μ§λ€.
~cpp void MacroCommand::Add (Command* c) { _cmds->Append (c); } void MacroCommand::Remove (Command* c) { _cmds->Remove (c); }
1.11. Known Uses ¶
μλ§λ CommandPatternμ λν 첫λ²μ§Έ μμ λ Lieberman μ λ
Όλ¬Έ(Lie85)μμ λνλ¬μ κ²μ΄λ€. MacApp App89 λ undoκ°λ₯ν λͺ
λ Ήμ ꡬνμ μν commandμ νκΈ°λ₯Ό λμ€νμμΌ°λ€. ET++WGM88, InterViews LCI+92, UnidrawVL90 μμ CommandPatterμ λ°λΌ ν΄λμ€λ€μ μ μνλ€. InterViewsλ κ° κΈ°λ₯λ³ λͺ
λ Ήμ λν Action μΆμ ν΄λμ€λ₯Ό μ μνλ€. κ·Έλ¦¬κ³ action λ©μλμ μν΄ μΈμνλ¨μΌλ‘μ μλμ μΌλ‘ command subclassλ€μ μΈμ€ν΄μ€ν μν€λ ActionCallback ν
νλ¦Ώλ μ μνμλ€.
THINK ν΄λμ€ λΌμ΄λΈλ¬λ¦¬ Sym93b λν undo κ°λ₯ν λͺ
λ Ήμ μ§μνκΈ° μν΄ CommandPatternμ μ¬μ©νλ€. THINK μμμ Commandλ€μ "Tasks" λ‘ λΆλ¦°λ€. Task κ°μ²΄λ€μ ChainOfResponsibilityPatternμ μ
κ°νμ¬ λ겨μ§κ³ μλΉλμ΄μ§λ€.
AddMe)