66

私の質問は、次の抽象化 (C# コード) があるコマンド パターンに関連しています。

public interface ICommand
{
    void Execute();
}

アプリケーションからエンティティを削除することを目的とした、単純な具体的なコマンドを見てみましょう。Personたとえば、インスタンス。

DeletePersonCommand実装する がありますICommand。このコマンドは、メソッドが呼び出されPersonたときに削除するために、パラメータとして削除する必要があります。Execute

パラメータ化されたコマンドを管理する最良の方法は何ですか? コマンドを実行する前に、コマンドにパラメーターを渡す方法は?

4

13 に答える 13

71

コンストラクターまたはセッター注入 (または同等のもの) によって、パラメーターをコマンド オブジェクトに関連付ける必要があります。おそらく次のようなものです:

public class DeletePersonCommand: ICommand
{
     private Person personToDelete;
     public DeletePersonCommand(Person personToDelete)
     {
         this.personToDelete = personToDelete;
     }

     public void Execute()
     {
        doSomethingWith(personToDelete);
     }
}
于 2008-09-19T19:48:06.793 に答える
23

コンストラクターまたはセッターを介してデータを渡すことは機能しますが、コマンドの作成者はコマンドが必要とするデータを知る必要があります...

「コンテキスト」のアイデアは非常に優れており、しばらく前にそれを活用した (内部の) フレームワークに取り組んでいました。

コントローラー (ユーザーと対話する UI コンポーネント、ユーザー コマンドを解釈する CLI、着信パラメーターとセッション データを解釈するサーブレットなど) をセットアップして、使用可能なデータへの名前付きアクセスを提供すると、コマンドは必要なデータを直接要求できます。

このようなセットアップが可能にする分離が本当に好きです。階層化については、次のように考えてください。

User Interface (GUI controls, CLI, etc)
    |
[syncs with/gets data]
    V
Controller / Presentation Model
    |                    ^
[executes]               |
    V                    |
Commands --------> [gets data by name]
    |
[updates]
    V
Domain Model

これを「正しく」行えば、同じコマンドとプレゼンテーション モデルをあらゆる種類のユーザー インターフェイスで使用できます。

これをさらに一歩進めると、上記の「コントローラー」はかなり一般的です。UI コントロールは、呼び出すコマンドの名前を知っていればよいだけです。UI コントロール (またはコントローラー) は、そのコマンドの作成方法や、そのコマンドが必要とするデータについての知識を持っている必要はありません。ここが本当の利点です。

たとえば、マップで実行するコマンドの名前を保持できます。コンポーネントが「トリガー」(通常は actionPerformed) されるたびに、コントローラーはコマンド名を検索し、それをインスタンス化し、execute を呼び出し、元に戻すスタック (使用している場合) にプッシュします。

于 2008-09-25T22:21:27.497 に答える
12

いくつかのオプションがあります:

プロパティまたはコンストラクターによってパラメーターを渡すことができます。

他のオプションは次のとおりです。

interface ICommand<T>
{
    void Execute(T args);
}

また、すべてのコマンド パラメータを値オブジェクトにカプセル化します。

于 2008-09-19T19:48:11.690 に答える
8

私の実装は次のようになります(Juanmaによって提案されたICommandを使用):

public class DeletePersonCommand: ICommand<Person>
{
    public DeletePersonCommand(IPersonService personService)
    {  
        this.personService = personService;
    }

    public void Execute(Person person)
    {
        this.personService.DeletePerson(person);
    }
}

IPersonServiceはIPersonRepositoryである可能性があり、コマンドがどの「レイヤー」であるかによって異なります。

于 2010-03-21T05:31:45.550 に答える
6

コマンド オブジェクトを作成するときに人を渡します。

ICommand command = new DeletePersonCommand(person);

コマンドを実行すると、知る必要があるすべてのことを既に知っているようになります。

class DeletePersonCommand : ICommand
{
   private Person person;
   public DeletePersonCommand(Person person)
   {
      this.person = person;
   }

   public void Execute()
   {
      RealDelete(person);
   }
}
于 2008-09-19T19:53:23.817 に答える
6

この場合、Command オブジェクトで行ったことは、本質的にマップである Context オブジェクトを作成することです。マップには名前と値のペアが含まれており、キーは定数であり、値はコマンドの実装で使用されるパラメーターです。後のコマンドが前のコマンドからのコンテキストの変更に依存するコマンド チェーンがある場合に特に便利です。

したがって、実際の方法は次のようになります

void execute(Context ctx);
于 2008-09-19T19:55:00.520 に答える
5

コンストラクターで、フィールドとして格納されます。

また、最終的には、元に戻すスタックまたはファイルの永続性のために、ICommand をシリアル化できるようにする必要があります。

于 2008-09-19T19:46:31.477 に答える
3

C#/WPF のパターンに基づいて、ICommand インターフェイス (System.Windows.Input.ICommand) が定義され、CanExecute メソッドだけでなく、Execute のパラメーターとしてオブジェクトを受け取ります。

interface ICommand
            {
                bool CanExecute(object parameter);
                void Execute(object parameter);
            }

これにより、ICommand を実装するカスタム コマンド オブジェクトのインスタンスである static public フィールドとしてコマンドを定義できます。

public static ICommand DeleteCommand = new DeleteCommandInstance();

このようにして、execute が呼び出されたときに、関連するオブジェクト (あなたの場合は人) が渡されます。その後、Execute メソッドはオブジェクトをキャストし、Delete() メソッドを呼び出すことができます。

public void Execute(object parameter)
            {
                person target = (person)parameter;
                target.Delete();
            } 
于 2008-09-19T20:02:49.533 に答える
2

使用するパラメーターを含む CommandArgs オブジェクトを作成する必要があります。Command オブジェクトのコンストラクターを使用して CommandArgs オブジェクトを挿入します。

于 2008-09-21T15:43:14.507 に答える
0

DeletePersonCommand は、そのコンストラクターまたはメソッドにパラメーターを持つことができます。DeletePersonCommand には Execute() があり、execute では、Execute() の呼び出しの前に Getter/Setter によって渡される属性を確認できます。

于 2008-09-19T19:47:04.470 に答える
0

のコンストラクターに必要な引数を追加しますDeletePersonCommand。次に、Execute()が呼び出されると、構築時にオブジェクトに渡されたパラメータが使用されます。

于 2008-09-19T19:47:05.220 に答える
-5

「Person」にある種の IDeletable インターフェイスを実装させてから、エンティティが使用する基本クラスまたはインターフェイスをコマンドに使用させます。そうすれば、エンティティを IDeletable にキャストしようとする DeleteCommand を作成できます。それが機能する場合は、.Delete を呼び出します。

public class DeleteCommand : ICommand
{
   public void Execute(Entity entity)
   {
      IDeletable del = entity as IDeletable;
      if (del != null) del.Delete();
   }
}
于 2008-09-19T19:48:04.857 に答える