8

わかりましたので、おおよそ次のようなコードを探しています。

void DoSomething(object o)
{
    if (o is Sometype1) { 
    //cast o to Sometype and do something to it
    }
    else if (o is Sometype2) {
    //cast o to Sometype2 and do something to it
    }
    ...
    else if (o is SometypeN) {
    //cast o to SometypeN and do something to it
    }
}

ここで、1 つのアプローチはo、パラメーターとして使用されるすべてのオブジェクトに、次のようなインターフェイスを実装させることです。

interface ICanHaveSomethingDoneToMe
{
    //expose various properties that the DoSomething method wants to access
}

しかし、これの問題は、すべてのオブジェクトにこのインターフェイスを実装させたくないということです。何かを行うメソッドのロジックは、実際にはオブジェクトに属していません。これに対処するには、どのパターンを使用する必要がありますか?

の一連の実装のようなものを疑っています

interface IPropertiesForDoingSomethingTo<T>
{
    //expose various properties that the DoSomething method wants to access
}

良いかもしれません。実装したいオブジェクトの種類ごとに実装する必要がありますが、この新しい問題が発生します。私は時点で次のような方法が必要です

IPropertiesForDoingSomethingTo<T> GetPropsGeneric(T t);

しかし、これには大規模なスイッチが必要ですか? 次のようなメソッドがたくさんあるクラスを定義する必要がありますか

IPropertiesForDoingSomethingTo<Someobject1> GetProps(Someobject1 t);
...
IPropertiesForDoingSomethingTo<Someobject1> GetProps(SomeobjectN t);

これには、実行時に新しい型を追加できないという一般的なバージョンと比較して問題があります。コンテナーを解決するために、GetPropsGeneric の DI コンテナーでできる狡猾な何かがありますか? ありがとう!

4

6 に答える 6

6

オブジェクトの型をチェックしている switch ステートメント (または一連の if ステートメント) を目にするときはいつでも、これは欠落している基本クラスまたはインターフェースの重大な危険信号です。つまり、コードはオブジェクト タイプをテストするのではなく、ポリモーフィズムに依存する必要があります。

基本クラスを変更したり、インターフェイスを実装したりできない場合は、動的ディスパッチをシミュレートするための辞書が残っている可能性があります。C# では、キャストを含むメソッドに匿名デリゲートを使用できます

プロパティ アクセスに関しては、プロパティが準拠しておらず、リフレクションを介したアクセスがオプションでない場合は、上記のメソッド/デリゲートでプロパティ値を抽出し、代わりに汎用関数に渡す必要がある場合があります。

于 2008-11-20T17:55:15.580 に答える
2

C# を使用しているようです。すでに確立されているクラスにアタッチする「拡張メソッド」を作成できると思います。

もう 1 つの方法は、型ごとにハンドラー デリゲートを作成し、デリゲートへの参照をオブジェクト型をキーとするハッシュテーブルに格納することです。

次に、「DoSomething」メソッドは、渡されたオブジェクトのタイプによって適切なデリゲートを検索して実行できます。

于 2008-11-20T17:54:17.983 に答える
0

私はスティーブンに同意します。また、この問題のコンテキストは二重ディスパッチの問題を思い出させました。したがって、ビジター パターンが適切な解決策である可能性があります。ただし、階層に一部のインターフェイス定義が欠けていることは明らかです。

于 2010-04-01T14:07:48.667 に答える
0

実際の例がより役に立ちます。@Steven A. Loweが言うように、関連するクラスのファミリのメソッドの実装を単に変更する場合は、ポリモーフィズムを使用し、これにサブクラスの関係を使用することをお勧めします。クラスが「is a」関係に参加していない場合は、Visitorなどの他のパタ​​ーンがより適切な場合があります。

于 2008-11-20T18:06:41.030 に答える
0

ポリモーフィズムは、基本オブジェクトが渡される答えです。しかし、それはおそらくあなたが望むよりもはるかに定型的でセマンティックな複雑さです。

機能を何らかの方法で派生クラスにシャントし、「仮想」関数を実装する必要があります。

于 2008-11-20T18:07:27.020 に答える
0

これは、アスペクト指向プログラミングのアプローチの問題だと思います。

DoSomething メソッドに ICanHaveSomethingDone インターフェイスをパラメーターとして使用してもらいたいと思います。次に、ICanHaveSomethinghgDone インターフェイスを定義し、そこから DoSomethingToMe を実装するサブクラス (DoSomething を実行するオブジェクトごとに 1 つ) を、実装クラスごとに異なる方法で派生させます。それらのそれぞれは、何かをしたい型のコンストラクターを取るだけなので、DoSomething を呼び出すときに、実際に Factory を呼び出します (非常に単純で、入力型から ICanHaveSomethingDone クラスのインスタンスを作成するだけです)。 DoSomethingToMe メソッドを実装し、基になるオブジェクトの適切なコードを持つクラスのインスタンスを作成します。

基本的に、このように考えてください。パラメーター オブジェクトに実装するインターフェイス コントラクトを定義しています。オブジェクトのサブクラスの形式で「装飾」を定義し、特定のクラスのインターフェイス動作の特定の実装を実装する (したがって、契約を履行する) インターフェイス。このようにして、各クラスの DoSomething メソッドの実装を、それらのクラスのソースから完全に分離することができます。

これが行うもう1つのこと。これは、ファクトリを DI コンテナーにすると、実行時に新しい型を追加できることを意味します。インターフェイスとそのクラスから派生したクラスとして定義された実行したいアクションの実装がある限り、何かを実行できるようにしたい新しい型をファクトリ コンテナーに注入することによって、 あなたは上手い。完全な AOP アプローチを実装すれば、派生クラスを実装せずに実行時に動作を定義することもできます。インターフェイスを定義し、アクションでの動作を定義し、派生クラスの実装をパラメーター化して、実行時に渡すオブジェクトで必要な動作を一緒に構成します。しかし、それは複雑です... :-)

ところで、Spring AOP はこの点で優れています。私はそれを読み上げます。

于 2008-11-20T18:09:10.557 に答える