// 后进... method push(c: Command) is // 将命令压入历史记录数组的末尾。
// ...先出 method pop():Command is // 从历史记录中取出最近的命令。
// 编辑器类包含实际的文本编辑操作。它会担任接收者的角色:最后所有命令都会 // 将执行工作委派给编辑器的方法。 class Editor is field text: string
method getSelection() is // 返回选中的文字。
method deleteSelection() is // 删除选中的文字。
method replaceSelection(text) is // 在当前位置插入剪贴板中的内容。
// 应用程序类会设置对象之间的关系。它会担任发送者的角色:当需要完成某些工 // 作时,它会创建并执行一个命令对象。 class Application is field clipboard: string field editors: arrayof Editors field activeEditor: Editor field history: CommandHistory
namespaceRefactoringGuru.DesignPatterns.Command.Conceptual { // The Command interface declares a method for executing a command. publicinterfaceICommand { voidExecute(); }
// Some commands can implement simple operations on their own. classSimpleCommand : ICommand { privatestring _payload = string.Empty;
publicvoidExecute() { Console.WriteLine($"SimpleCommand: See, I can do simple things like printing ({this._payload})"); } }
// However, some commands can delegate more complex operations to other // objects, called "receivers." classComplexCommand : ICommand { private Receiver _receiver;
// Context data, required for launching the receiver's methods. privatestring _a;
privatestring _b;
// Complex commands can accept one or several receiver objects along // with any context data via the constructor. publicComplexCommand(Receiver receiver, string a, string b) { this._receiver = receiver; this._a = a; this._b = b; }
// Commands can delegate to any methods of a receiver. publicvoidExecute() { Console.WriteLine("ComplexCommand: Complex stuff should be done by a receiver object."); this._receiver.DoSomething(this._a); this._receiver.DoSomethingElse(this._b); } }
// The Receiver classes contain some important business logic. They know how // to perform all kinds of operations, associated with carrying out a // request. In fact, any class may serve as a Receiver. classReceiver { publicvoidDoSomething(string a) { Console.WriteLine($"Receiver: Working on ({a}.)"); }
publicvoidDoSomethingElse(string b) { Console.WriteLine($"Receiver: Also working on ({b}.)"); } }
// The Invoker is associated with one or several commands. It sends a // request to the command. classInvoker { private ICommand _onStart;
// The Invoker does not depend on concrete command or receiver classes. // The Invoker passes a request to a receiver indirectly, by executing a // command. publicvoidDoSomethingImportant() { Console.WriteLine("Invoker: Does anybody want something done before I begin?"); if (this._onStart is ICommand) { this._onStart.Execute(); } Console.WriteLine("Invoker: ...doing something really important..."); Console.WriteLine("Invoker: Does anybody want something done after I finish?"); if (this._onFinish is ICommand) { this._onFinish.Execute(); } } }
classProgram { staticvoidMain(string[] args) { // The client code can parameterize an invoker with any commands. Invoker invoker = new Invoker(); invoker.SetOnStart(new SimpleCommand("Say Hi!")); Receiver receiver = new Receiver(); invoker.SetOnFinish(new ComplexCommand(receiver, "Send email", "Save report"));
invoker.DoSomethingImportant(); } } }
Output.txt: 执行结果
1 2 3 4 5 6 7
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object. Receiver: Working on (Send email.) Receiver: Also working on (Save report.)
在 C++ 中使用模式
复杂度: ★☆☆
流行度: ★★★
使用示例: 命令模式在 C++ 代码中很常见。 大部分情况下, 它被用于代替包含行为的参数化 UI 元素的回调函数, 此外还被用于对任务进行排序和记录操作历史记录等。
/** * The Command interface declares a method for executing a command. */ classCommand { public: virtual ~Command() { } virtualvoidExecute()const= 0; }; /** * Some commands can implement simple operations on their own. */ classSimpleCommand : public Command { private: std::string pay_load_;
public: explicitSimpleCommand(std::string pay_load) : pay_load_(pay_load) { } voidExecute()constoverride{ std::cout << "SimpleCommand: See, I can do simple things like printing (" << this->pay_load_ << ")\n"; } };
/** * The Receiver classes contain some important business logic. They know how to * perform all kinds of operations, associated with carrying out a request. In * fact, any class may serve as a Receiver. */ classReceiver { public: voidDoSomething(const std::string &a){ std::cout << "Receiver: Working on (" << a << ".)\n"; } voidDoSomethingElse(const std::string &b){ std::cout << "Receiver: Also working on (" << b << ".)\n"; } };
/** * However, some commands can delegate more complex operations to other objects, * called "receivers." */ classComplexCommand : public Command { /** * @var Receiver */ private: Receiver *receiver_; /** * Context data, required for launching the receiver's methods. */ std::string a_; std::string b_; /** * Complex commands can accept one or several receiver objects along with any * context data via the constructor. */ public: ComplexCommand(Receiver *receiver, std::string a, std::string b) : receiver_(receiver), a_(a), b_(b) { } /** * Commands can delegate to any methods of a receiver. */ voidExecute()constoverride{ std::cout << "ComplexCommand: Complex stuff should be done by a receiver object.\n"; this->receiver_->DoSomething(this->a_); this->receiver_->DoSomethingElse(this->b_); } };
/** * The Invoker is associated with one or several commands. It sends a request to * the command. */ classInvoker { /** * @var Command */ private: Command *on_start_; /** * @var Command */ Command *on_finish_; /** * Initialize commands. */ public: ~Invoker() { delete on_start_; delete on_finish_; }
voidSetOnStart(Command *command){ this->on_start_ = command; } voidSetOnFinish(Command *command){ this->on_finish_ = command; } /** * The Invoker does not depend on concrete command or receiver classes. The * Invoker passes a request to a receiver indirectly, by executing a command. */ voidDoSomethingImportant(){ std::cout << "Invoker: Does anybody want something done before I begin?\n"; if (this->on_start_) { this->on_start_->Execute(); } std::cout << "Invoker: ...doing something really important...\n"; std::cout << "Invoker: Does anybody want something done after I finish?\n"; if (this->on_finish_) { this->on_finish_->Execute(); } } }; /** * The client code can parameterize an invoker with any commands. */
intmain(){ Invoker *invoker = new Invoker; invoker->SetOnStart(newSimpleCommand("Say Hi!")); Receiver *receiver = new Receiver; invoker->SetOnFinish(newComplexCommand(receiver, "Send email", "Save report")); invoker->DoSomethingImportant();
delete invoker; delete receiver;
return0; }
Output.txt: 执行结果
1 2 3 4 5 6 7
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object. Receiver: Working on (Send email.) Receiver: Also working on (Save report.)
publicfunctionexecute(): void { echo"SimpleCommand: See, I can do simple things like printing (" . $this->payload . ")\n"; } }
/** * However, some commands can delegate more complex operations to other objects, * called "receivers." */ classComplexCommandimplementsCommand { /** * @var Receiver */ private$receiver;
/** * Context data, required for launching the receiver's methods. */ private$a;
private$b;
/** * Complex commands can accept one or several receiver objects along with * any context data via the constructor. */ publicfunction__construct(Receiver $receiver, string$a, string$b) { $this->receiver = $receiver; $this->a = $a; $this->b = $b; }
/** * Commands can delegate to any methods of a receiver. */ publicfunctionexecute(): void { echo"ComplexCommand: Complex stuff should be done by a receiver object.\n"; $this->receiver->doSomething($this->a); $this->receiver->doSomethingElse($this->b); } }
/** * The Receiver classes contain some important business logic. They know how to * perform all kinds of operations, associated with carrying out a request. In * fact, any class may serve as a Receiver. */ classReceiver { publicfunctiondoSomething(string$a): void { echo"Receiver: Working on (" . $a . ".)\n"; }
publicfunctiondoSomethingElse(string$b): void { echo"Receiver: Also working on (" . $b . ".)\n"; } }
/** * The Invoker is associated with one or several commands. It sends a request to * the command. */ classInvoker { /** * @var Command */ private$onStart;
/** * The Invoker does not depend on concrete command or receiver classes. The * Invoker passes a request to a receiver indirectly, by executing a * command. */ publicfunctiondoSomethingImportant(): void { echo"Invoker: Does anybody want something done before I begin?\n"; if ($this->onStart instanceof Command) { $this->onStart->execute(); }
echo"Invoker: Does anybody want something done after I finish?\n"; if ($this->onFinish instanceof Command) { $this->onFinish->execute(); } } }
/** * The client code can parameterize an invoker with any commands. */ $invoker = newInvoker(); $invoker->setOnStart(newSimpleCommand("Say Hi!")); $receiver = newReceiver(); $invoker->setOnFinish(newComplexCommand($receiver, "Send email", "Save report"));
$invoker->doSomethingImportant();
Output.txt: 执行结果
1 2 3 4 5 6 7
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object. Receiver: Working on (Send email.) Receiver: Also working on (Save report.)
/** * The Command interface declares the main execution method as well as several * helper methods for retrieving a command's metadata. */ interfaceCommand { publicfunctionexecute(): void;
publicfunctiongetId(): int;
publicfunctiongetStatus(): int; }
/** * The base web scraping Command defines the basic downloading infrastructure, * common to all concrete web scraping commands. */ abstractclassWebScrapingCommandimplementsCommand { public$id;
public$status = 0;
/** * @var string URL for scraping. */ public$url;
/** * Since the execution methods for all web scraping commands are very * similar, we can provide a default implementation and let subclasses * override them if needed. * * Psst! An observant reader may spot another behavioral pattern in action * here. */ publicfunctionexecute(): void { $html = $this->download(); $this->parse($html); $this->complete(); }
/** * The Concrete Command for scraping the list of movie genres. */ classIMDBGenresScrapingCommandextendsWebScrapingCommand { publicfunction__construct() { $this->url = "https://www.imdb.com/feature/genre/"; }
/** * Extract all genres and their search URLs from the page: * https://www.imdb.com/feature/genre/ */ publicfunctionparse($html): void { preg_match_all("|href=\"(https://www.imdb.com/search/title\?genres=.*?)\"|", $html, $matches); echo"IMDBGenresScrapingCommand: Discovered " . count($matches[1]) . " genres.\n";
/** * The Concrete Command for scraping the list of movies in a specific genre. */ classIMDBGenrePageScrapingCommandextendsWebScrapingCommand { private$page;
// Parse the next page URL. if (preg_match("|Next »</a>|", $html)) { Queue::get()->add(newIMDBGenrePageScrapingCommand($this->url, $this->page + 1)); } } }
/** * The Concrete Command for scraping the movie details. */ classIMDBMovieScrapingCommandextendsWebScrapingCommand { /** * Get the movie info from a page like this: * https://www.imdb.com/title/tt4154756/ */ publicfunctionparse(string$html): void { if (preg_match("|<h1 itemprop=\"name\" class=\"\">(.*?)</h1>|", $html, $matches)) { $title = $matches[1]; } echo"IMDBMovieScrapingCommand: Parsed movie $title.\n"; } }
/** * The Queue class acts as an Invoker. It stacks the command objects and * executes them one by one. If the script execution is suddenly terminated, the * queue and all its commands can easily be restored, and you won't need to * repeat all of the executed commands. * * Note that this is a very primitive implementation of the command queue, which * stores commands in a local SQLite database. There are dozens of robust queue * solution available for use in real apps. */ classQueue { private$db;
/** * For our convenience, the Queue object is a Singleton. */ publicstaticfunctionget(): Queue { static$instance; if (!$instance) { $instance = newQueue(); }
return$instance; } }
/** * The client code. */
$queue = Queue::get();
if ($queue->isEmpty()) { $queue->add(newIMDBGenresScrapingCommand()); }
defexecute(self) -> None: print(f"SimpleCommand: See, I can do simple things like printing" f"({self._payload})")
classComplexCommand(Command): """ However, some commands can delegate more complex operations to other objects, called "receivers." """
def__init__(self, receiver: Receiver, a: str, b: str) -> None: """ Complex commands can accept one or several receiver objects along with any context data via the constructor. """
self._receiver = receiver self._a = a self._b = b
defexecute(self) -> None: """ Commands can delegate to any methods of a receiver. """
print("ComplexCommand: Complex stuff should be done by a receiver object", end="") self._receiver.do_something(self._a) self._receiver.do_something_else(self._b)
classReceiver: """ The Receiver classes contain some important business logic. They know how to perform all kinds of operations, associated with carrying out a request. In fact, any class may serve as a Receiver. """
defdo_something(self, a: str) -> None: print(f"\nReceiver: Working on ({a}.)", end="")
defdo_something_else(self, b: str) -> None: print(f"\nReceiver: Also working on ({b}.)", end="")
classInvoker: """ The Invoker is associated with one or several commands. It sends a request to the command. """
defdo_something_important(self) -> None: """ The Invoker does not depend on concrete command or receiver classes. The Invoker passes a request to a receiver indirectly, by executing a command. """
print("Invoker: Does anybody want something done before I begin?") ifisinstance(self._on_start, Command): self._on_start.execute()
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object Receiver: Working on (Send email.) Receiver: Also working on (Save report.)
# The Command interface declares a method for executing a command. classCommand # @abstract defexecute raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'" end end
# Some commands can implement simple operations on their own. classSimpleCommand < Command # @param [String] payload definitialize(payload) @payload = payload end
defexecute puts "SimpleCommand: See, I can do simple things like printing (#{@payload})" end end
# However, some commands can delegate more complex operations to other objects, # called "receivers". classComplexCommand < Command # Complex commands can accept one or several receiver objects along with any # context data via the constructor. definitialize(receiver, a, b) @receiver = receiver @a = a @b = b end
# Commands can delegate to any methods of a receiver. defexecute print 'ComplexCommand: Complex stuff should be done by a receiver object' @receiver.do_something(@a) @receiver.do_something_else(@b) end end
# The Receiver classes contain some important business logic. They know how to # perform all kinds of operations, associated with carrying out a request. In # fact, any class may serve as a Receiver. classReceiver # @param [String] a defdo_something(a) print "\nReceiver: Working on (#{a}.)" end
# @param [String] b defdo_something_else(b) print "\nReceiver: Also working on (#{b}.)" end end
# The Invoker is associated with one or several commands. It sends a request to # the command. classInvoker # Initialize commands.
# @param [Command] command defon_start=(command) @on_start = command end
# @param [Command] command defon_finish=(command) @on_finish = command end
# The Invoker does not depend on concrete command or receiver classes. The # Invoker passes a request to a receiver indirectly, by executing a command. defdo_something_important puts 'Invoker: Does anybody want something done before I begin?' @on_start.execute if@on_start.is_a? Command
puts 'Invoker: Does anybody want something done after I finish?' @on_finish.execute if@on_finish.is_a? Command end end
# The client code can parameterize an invoker with any commands. invoker = Invoker.new invoker.on_start = SimpleCommand.new('Say Hi!') receiver = Receiver.new invoker.on_finish = ComplexCommand.new(receiver, 'Send email', 'Save report')
invoker.do_something_important
output.txt: 执行结果
1 2 3 4 5 6 7
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object Receiver: Working on (Send email.) Receiver: Also working on (Save report.)
在 Swift 中使用模式
复杂度: ★☆☆
流行度: ★★★
使用示例: 命令模式在 Swift 代码中很常见。 大部分情况下, 它被用于代替包含行为的参数化 UI 元素的回调函数, 此外还被用于对任务进行排序和记录操作历史记录等。
/// The Command interface declares a method for executing a command. protocolCommand {
funcexecute() }
/// Some commands can implement simple operations on their own. classSimpleCommand: Command {
privatevar payload: String
init(_payload: String) { self.payload = payload }
funcexecute() { print("SimpleCommand: See, I can do simple things like printing ("+ payload +")") } }
/// However, some commands can delegate more complex operations to other /// objects, called "receivers." classComplexCommand: Command {
privatevar receiver: Receiver
/// Context data, required for launching the receiver's methods. privatevar a: String privatevar b: String
/// Complex commands can accept one or several receiver objects along with /// any context data via the constructor. init(_receiver: Receiver, _a: String, _b: String) { self.receiver = receiver self.a = a self.b = b }
/// Commands can delegate to any methods of a receiver. funcexecute() { print("ComplexCommand: Complex stuff should be done by a receiver object.\n") receiver.doSomething(a) receiver.doSomethingElse(b) } }
/// The Receiver classes contain some important business logic. They know how to /// perform all kinds of operations, associated with carrying out a request. In /// fact, any class may serve as a Receiver. classReceiver {
funcdoSomething(_a: String) { print("Receiver: Working on ("+ a +")\n") }
funcdoSomethingElse(_b: String) { print("Receiver: Also working on ("+ b +")\n") } }
/// The Invoker is associated with one or several commands. It sends a request /// to the command. classInvoker {
/// The Invoker does not depend on concrete command or receiver classes. The /// Invoker passes a request to a receiver indirectly, by executing a /// command. funcdoSomethingImportant() {
print("Invoker: Does anybody want something done before I begin?")
onStart?.execute()
print("Invoker: ...doing something really important...") print("Invoker: Does anybody want something done after I finish?")
onFinish?.execute() } }
/// Let's see how it all comes together. classCommandConceptual: XCTestCase {
functest() { /// The client code can parameterize an invoker with any commands.
let invoker =Invoker() invoker.setOnStart(SimpleCommand("Say Hi!"))
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object.
publicexecute(): void { console.log(`SimpleCommand: See, I can do simple things like printing (${this.payload})`); } }
/** * However, some commands can delegate more complex operations to other objects, * called "receivers." */ classComplexCommandimplementsCommand { privatereceiver: Receiver;
/** * Context data, required for launching the receiver's methods. */ privatea: string;
privateb: string;
/** * Complex commands can accept one or several receiver objects along with * any context data via the constructor. */ constructor(receiver: Receiver, a: string, b: string) { this.receiver = receiver; this.a = a; this.b = b; }
/** * Commands can delegate to any methods of a receiver. */ publicexecute(): void { console.log('ComplexCommand: Complex stuff should be done by a receiver object.'); this.receiver.doSomething(this.a); this.receiver.doSomethingElse(this.b); } }
/** * The Receiver classes contain some important business logic. They know how to * perform all kinds of operations, associated with carrying out a request. In * fact, any class may serve as a Receiver. */ classReceiver { publicdoSomething(a: string): void { console.log(`Receiver: Working on (${a}.)`); }
publicdoSomethingElse(b: string): void { console.log(`Receiver: Also working on (${b}.)`); } }
/** * The Invoker is associated with one or several commands. It sends a request to * the command. */ classInvoker { privateonStart: Command;
/** * The Invoker does not depend on concrete command or receiver classes. The * Invoker passes a request to a receiver indirectly, by executing a * command. */ publicdoSomethingImportant(): void { console.log('Invoker: Does anybody want something done before I begin?'); if (this.isCommand(this.onStart)) { this.onStart.execute(); }
console.log('Invoker: Does anybody want something done after I finish?'); if (this.isCommand(this.onFinish)) { this.onFinish.execute(); } }
privateisCommand(object): object is Command { returnobject.execute !== undefined; } }
/** * The client code can parameterize an invoker with any commands. */ const invoker = newInvoker(); invoker.setOnStart(newSimpleCommand('Say Hi!')); const receiver = newReceiver(); invoker.setOnFinish(newComplexCommand(receiver, 'Send email', 'Save report'));
invoker.doSomethingImportant();
Output.txt: 执行结果
1 2 3 4 5 6 7
Invoker: Does anybody want something done before I begin? SimpleCommand: See, I can do simple things like printing (Say Hi!) Invoker: ...doing something really important... Invoker: Does anybody want something done after I finish? ComplexCommand: Complex stuff should be done by a receiver object. Receiver: Working on (Send email.) Receiver: Also working on (Save report.)
概念示例
下面我们通过电视机的例子来了解命令模式。 你可通过一下方式打开电视机:
按下遥控器上的 ON 开关;
按下电视机上的 ON 开关。
我们可以从实现 ON 命令对象并以电视机作为接收者入手。 当在此命令上调用 execute执行方法时, 方法会调用 TV.on打开电视函数。 最后的工作是定义请求者: 这里实际上有两个请求者: 遥控器和电视机。 两者都将嵌入 ON 命令对象。