[[TableOfContents]] = Command = == Intent == request 를 ê°ì²´ë¡œ 캡ìŠí™” 시킴으로서 다른 requestë“¤ì„ ê°€ì§„ í´ë¼ì´ì–¸íŠ¸ë¥¼ ì¸ìží™”시키거나, request를 queue하거나 대기시키며, undoê°€ 가능한 ëª…ë ¹ì„ ì§€ì›í•œë‹¤. == Also Known As == Action, Transaction == 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. http://zeropage.org/~reset/zb/data/comma081.gif 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 한다. http://zeropage.org/~reset/zb/data/comma078.gif OpenCommandì˜ Execute operationì€ ë‹¤ë¥´ë‹¤. OpenCommand는 사용ìžì—게 문서 ì´ë¦„ì„ ë¬¼ì€ë’¤, 대ì‘하는 Document ê°ì²´ë¥¼ ë§Œë“¤ê³ , 해당 문서를 여는 어플리케ì´ì…˜ì— 문서를 추가한 ë’¤ (MDI를 ìƒê°í• 것) 문서를 연다. http://zeropage.org/~reset/zb/data/comma079.gif 때때로 MenuItemì€ ì—°ì†ëœ ëª…ë ¹ì–´ë“¤ì˜ ì¼ê´„ìˆ˜í–‰ì„ í•„ìš”ë¡œ 한다. 예를 들어서 해당 페ì´ì§€ë¥¼ ì¤‘ì•™ì— ë†“ê³ ì¼ë°˜í¬ê¸°í™” 시키는 MenuItemì€ CenterDocumentCommand ê°ì²´ì™€ NormalSizeCommand ê°ì²´ë¡œ 만들 수 있다. ì´ëŸ¬í•œ ë°©ì‹ìœ¼ë¡œ ëª…ë ¹ì–´ë“¤ì„ ì´ì–´ì§€ê²Œ 하는 ê²ƒì€ ì¼ë°˜ì ì´ë¯€ë¡œ, 우리는 ë³µìˆ˜ëª…ë ¹ì„ ìˆ˜í–‰í•˜ê¸° 위한 MenuItemì„ í—ˆìš©í•˜ê¸° 위해 MacroCommand를 ì •ì˜í• 수 있다. MacroCommand는 단순히 ëª…ë ¹ì–´ë“¤ì˜ sequence를 수행하는 Command subclassì˜ êµ¬ì²´í™”ì´ë‹¤. MacroCommand는 MacroCommand를 ì´ë£¨ê³ 있는 commandë“¤ì´ ê·¸ë“¤ì˜ receiver를 ì •ì˜í•˜ë¯€ë¡œ 명시ì ì¸ receiver를 가지지 않는다. http://zeropage.org/~reset/zb/data/comma080.gif ì´ëŸ¬í•œ 예들ì—ì„œ, 어떻게 Command patternì´ í•´ë‹¹ ëª…ë ¹ì„ invoke하는 ê°ì²´ì™€ ëª…ë ¹ì„ ìˆ˜í–‰í•˜ëŠ” ì •ë³´ë¥¼ 가진 ê°ì²´ë¥¼ 분리하는지 주목하ë¼. ì´ëŸ¬í•¨ì€ ìœ ì €ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ ë””ìžì¸í•¨ì— 있어서 ë§Žì€ ìœ ì—°ì„±ì„ ì œê³µí•œë‹¤. 어플리케ì´ì…˜ì€ 단지 menu와 push buttonì´ ê°™ì€ êµ¬ì²´ì ì¸ Command subclassì˜ ì¸ìŠ¤í„´ìŠ¤ë¥¼ ê³µìœ í•¨ìœ¼ë¡œì„œ menu 와 push button ì¸í„°íŽ˜ì´ìŠ¤ ì œê³µí• ìˆ˜ 있다. 우리는 ë™ì 으로 command를 바꿀 수 있으며, ì´ëŸ¬í•¨ì€ context-sensitive menu 를 êµ¬í˜„í•˜ëŠ”ë° ìœ ìš©í•˜ë‹¤. ë˜í•œ 우리는 ëª…ë ¹ì–´ë“¤ì„ ì»¤ë‹¤ëž€ ëª…ë ¹ì–´ì— í•˜ë‚˜ë¡œ 조합함으로서 command scriptingì„ ì§€ì›í• 수 있다. ì´ëŸ¬í•œ ëª¨ë“ ê²ƒì€ request를 issue하는 ê°ì²´ê°€ ì˜¤ì§ ì–´ë–»ê²Œ issueí™” 하는지만 ì•Œê³ ìžˆìœ¼ë©´ ë˜ê¸°ë•Œë¬¸ì— 가능하다. request를 나타내는 ê°ì²´ëŠ” 어떻게 requestê°€ 수행ë˜ì–´ì•¼ í• ì§€ ì•Œ 필요가 없다. == 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ë“¤ì„ ì‹œìŠ¤í…œì— í™•ìž¥ì‹œí‚¤ê¸° 쉽게 한다. == Structure == http://zeropage.org/~reset/zb/data/command.gif == Participants == * Command - ìˆ˜í–‰í• operationì„ ìœ„í•œ ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ ì„ ì–¸í•œë‹¤. * ConcreteCommand (PasteCommand, OpenCommand) - Receiver ê°ì²´ì™€ action 묶ìŒì„ ì •ì˜í•œë‹¤. * Client (Application) - ConcreteCommand ê°ì²´ë¥¼ ë§Œë“¤ê³ receiverë¡œ ì •í•œë‹¤. * Invoker (MenuItem) - command ì—게 request를 수행하ë„ë¡ ìš”ì²í•œë‹¤. * Receiver (Document, Application) - ì²˜ë¦¬í• requestì— ëŒ€í•´ ëª…ë ¹ì–´ë“¤ì„ ì–´ë–»ê²Œ 수행해야 í• ì§€ ì•Œê³ ìžˆë‹¤. ì–´ë– í•œ í´ëž˜ìŠ¤ë“ 지 Receiver로서 활ë™ê°€ëŠ¥í•˜ë‹¤. == Collaborations == * client는 ConcreteCommand ê°ì²´ë¥¼ ë§Œë“¤ê³ , receiver를 ì •í•œë‹¤. * Invoker ê°ì²´ëŠ” ConcreteCommandê°ì²´ë¥¼ ì €ìž¥í•œë‹¤. * invoker는 commandì—ì„œ Execute를 호출함으로서 request를 issue한다. ëª…ë ¹ì–´ê°€ undoê°€ëŠ¥í• ë•Œ, ConcreteCommand는 ëª…ë ¹ì–´ë¥¼ undo하기 위한 state를 ì €ìž¥í•œë‹¤. * ConcreteCommand ê°ì²´ëŠ” request를 처리하기 위해 receiverì—ì„œ operationì„ invoke한다. 다ìŒì˜ 다ì´ì–´ê·¸ëž¨ì€ ì´ ê°ì²´ë“¤ì´ 어떻게 ìƒí˜¸ìž‘용하는지 보여준다. ì´ ë‹¤ì´ì–´ê·¸ëž¨ì€ ë˜í•œ 어떻게 Command ê°€ receiver와 ì²˜ë¦¬í• request로부터 invoker를 분리하는지 설명한다. http://zeropage.org/~reset/zb/data/comma077.gif == Consequences == CommandPatternì€ ë‹¤ìŒê³¼ ê°™ì€ ê²°ê³¼ë¥¼ ê°€ì ¸ì˜¨ë‹¤. 1. Command는 해당 ê°ì²´ì˜ ëª…ë ¹ì„ invoke하는 ê°ì²´ì™€ 어떻게 수행해야 í• ì§€ ì•Œê³ ìžˆëŠ” ê°ì²´ì™€ì˜ ê²°í•©ì„ í•´ì œí•œë‹¤. 2. Command는 ì²«ë²ˆì§¸ë‹¨ê³„ì˜ í´ëž˜ìŠ¤ ê°ì²´ì´ë‹¤. Command는 ì¡°ìž‘ë˜ì–´ì§ˆ 수 있으면서 다른 ê°ì²´ë“¤ê³¼ 마찬가지로 확장가능하다. 3. Command를 ë¬¶ì„ ìˆ˜ 있다. ì•žì„œ 설명한 MacroCommandê°€ ê·¸ 예가 ëœë‹¤. ì¼ë°˜ì 으로 composite commandë“¤ì€ CompositePatternì˜ ì¸ìŠ¤í„´ìŠ¤ì´ë‹¤. 4. 새로운 Command를 추가하기가 쉽다. 왜ëƒí•˜ë©´ ì´ë¯¸ ì¡´ìž¬í•˜ê³ ìžˆëŠ” í´ëž˜ìŠ¤ë“¤ì„ ê³ ì¹ í•„ìš”ê°€ 없기 때문ì´ë‹¤. == Implementation == == 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); } }}} == Known Uses == ì•„ë§ˆë„ CommandPatternì— ëŒ€í•œ 첫번째 ì˜ˆì œëŠ” Lieberman ì˜ ë…¼ë¬¸([Lie85])ì—ì„œ ë‚˜íƒ€ë‚¬ì„ ê²ƒì´ë‹¤. MacApp [App89] 는 undo가능한 ëª…ë ¹ì˜ êµ¬í˜„ì„ ìœ„í•œ commandì˜ í‘œê¸°ë¥¼ 대중화시켰다. ET++[WGM88], InterViews [LCI+92], Unidraw[VL90] ì—ì‹œ CommandPatterì— ë”°ë¼ í´ëž˜ìŠ¤ë“¤ì„ ì •ì˜í–ˆë‹¤. InterViews는 ê° ê¸°ëŠ¥ë³„ ëª…ë ¹ì— ëŒ€í•œ Action ì¶”ìƒ í´ëž˜ìŠ¤ë¥¼ ì •ì˜í–ˆë‹¤. ê·¸ë¦¬ê³ action ë©”ì†Œë“œì— ì˜í•´ ì¸ìží™”ë¨ìœ¼ë¡œì„œ ìžë™ì 으로 command subclassë“¤ì„ ì¸ìŠ¤í„´ìŠ¤í™” 시키는 ActionCallback í…œí”Œë¦¿ë„ ì •ì˜í•˜ì˜€ë‹¤. THINK í´ëž˜ìŠ¤ ë¼ì´ë¸ŒëŸ¬ë¦¬ [Sym93b] ë˜í•œ undo 가능한 ëª…ë ¹ì„ ì§€ì›í•˜ê¸° 위해 CommandPatternì„ ì‚¬ìš©í•œë‹¤. THINK ì—ì„œì˜ Commandë“¤ì€ "Tasks" ë¡œ 불린다. Task ê°ì²´ë“¤ì€ ChainOfResponsibilityPatternì— ìž…ê°í•˜ì—¬ ë„˜ê²¨ì§€ê³ ì†Œë¹„ë˜ì–´ì§„다. AddMe) == Related Patterns == CompositePattern 는 MacroCommand를 êµ¬í˜„í•˜ëŠ”ë° ì´ìš©ë 수 있다. MementoPattern ì€ undo를 위한 state를 ìœ ì§€í• ìˆ˜ 있다. history list ì— ìœ„ì¹˜í•˜ê¸° ì „ì— ë³µì‚¬ë˜ì—¬ì•¼ í• command는 Prototype으로서 작용한다. ---- ["패턴분류"]