![Command](/images/patterns/cards/command-mini.png?id=b149eda017c0583c1e92343b83cfb1eb)
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.)