
Command を C# で
Command は、 振る舞いに関するデザインパターンの一つで、 リクエストや簡単な操作をオブジェクトに変換します。
変換により、 コマンドの遅延実行や遠隔実行を可能にしたり、 コマンドの履歴の保存を可能にしたりできます。
複雑度:
人気度:
使用例: Command パターンは、 C# コードではよく見かけます。 最もよく使われるのは、 UI 要素をアクションでパラメーター化する時のコールバックの代わりとしてです。 また、 タスクをキューに入れたり、 操作履歴の管理などでも使われます。
見つけ方: Command パターンは、 抽象またはインターフェース型 (送り手) 中の振る舞い系メソッド (複数) が違う抽象またはインターフェース型 (受け手) 中のある一つのメソッドを起動することから識別できます。 受け手は、 生成時にコマンドの実装によりカプセル化されています。 コマンドのクラスは通常特定のアクションに限定されています。
概念的な例
この例は、 Command デザインパターンの構造を説明するためのものです。 以下の質問に答えることを目的としています:
- どういうクラスからできているか?
- それぞれのクラスの役割は?
- パターンの要素同士はどう関係しているのか?
Program.cs: 概念的な例
using System; namespace RefactoringGuru.DesignPatterns.Command.Conceptual { // The Command interface declares a method for executing a command. public interface ICommand { void Execute(); } // Some commands can implement simple operations on their own. class SimpleCommand : ICommand { private string _payload = string.Empty; public SimpleCommand(string payload) { this._payload = payload; } public void Execute() { 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." class ComplexCommand : ICommand { private Receiver _receiver; // Context data, required for launching the receiver's methods. private string _a; private string _b; // Complex commands can accept one or several receiver objects along // with any context data via the constructor. public ComplexCommand(Receiver receiver, string a, string b) { this._receiver = receiver; this._a = a; this._b = b; } // Commands can delegate to any methods of a receiver. public void Execute() { 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. class Receiver { public void DoSomething(string a) { Console.WriteLine($"Receiver: Working on ({a}.)"); } public void DoSomethingElse(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. class Invoker { private ICommand _onStart; private ICommand _onFinish; // Initialize commands. public void SetOnStart(ICommand command) { this._onStart = command; } public void SetOnFinish(ICommand command) { this._onFinish = 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. public void DoSomethingImportant() { 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(); } } } class Program { static void Main(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: 実行結果
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.)