3

同じインターフェースのいくつかのインスタンスをさまざまな指定された方法で組み合わせるインターフェースを実装するための最良の方法は何ですか?複数のインターフェースに対してこれを行う必要があります。重要な本番システムでこれが必要なため、ボイラープレートを最小限に抑えながら、優れた効率を実現したいと考えています。

これが問題のスケッチです。

抽象的には、インスタンスを受け取り、さまざまなコンビネータを指定する汎用コンビネータクラスがあります。

class Combiner<I> {
   I[] instances;

   <T> T combineSomeWay(InstanceMethod<I,T> method) {
     // ... method.call(instances[i]) ... combined in some way ...
   }

   // more combinators
}

ここで、他の多くのインターフェイスの中で次のインターフェイスを実装したいとします。

Interface Foo {
  String bar(int baz);
}

私はこのようなコードで終わりたいです:

class FooCombiner implements Foo {
  Combiner<Foo> combiner;

  @Override 
  public String bar(final int baz) {
    return combiner.combineSomeWay(new InstanceMethod<Foo, String> {
      @Override public call(Foo instance) { return instance.bar(baz); } 
    });
  }
}

さて、インターフェースに多くのメソッドがある場合、これはすぐに長くなり、曲がりくねる可能性があります。JavaリフレクションAPIの動的プロキシを使用してそのようなインターフェースを実装できることは知っていますが、リフレクションを介したメソッドアクセスは100倍遅くなります。では、この場合の定型文と反射の代替案は何ですか?

4

2 に答える 2

2

動的プロキシを提案したと思いますが、最近の通常のメソッド呼び出しよりもはるかに遅いのでしょうか。リフレクションは、繰り返されるメソッド呼び出しを高速化するために、内部でかなりの魔法をかけると聞いています。(100倍遅い場合は、気付くと思いますか?わかりました。質問をもう一度読んでください。気付くでしょう!)

それ以外の場合は、基本的に質問の解決策があります。コマンドオブジェクトを使用して、インターフェイスの各メソッドをラップします。次に、インターフェイスのコレクション内の各インスタンスをコマンドオブジェクトに渡して処理できます。

もちろん、勇気と冒険心があれば、コマンドオブジェクトの実装と、cglib、javassist、またはその他の動的バイトコードジェネレーターを使用した動的クラス生成を使用したコンバイナーインターフェイスの実装を生成できます。それは定型文を回避するでしょう。

また、アスペクト、特にコンパイル時またはロード時のウィービングを使用したaspectJである程度の成功を収めることができるため、リフレクションのオーバーヘッドを回避できます。申し訳ありませんが、詳細をお伝えすることはできません。

于 2010-05-22T00:41:57.243 に答える
1

コンバイナーを逆にすることができます:

@Override
public String bar(int baz)
{
    //for (Foo f:combiner.combineSomeWay())// returns Iterator<Foo>
    for (Foo f:combiner) //combiner must implement Iterable<Foo> or Iterator<Foo>
    {
        // In case of several ways to combine
        // add() method should call some temp object
        // in combiner created (or installed) by 
        // combineSomeWay.
        // The best temp object to use is Iterator
        // returned by combiner.combineSomeWay();
        combiner.add(f.bar(baz));// or addResult, or addCallResult
    }
    // clear (or uninstall) temp object and result
    // thats why get* method 
    // name here is bad.
    return combiner.done(); 
}

ワンライナーではありませんが、理解しやすいです。ただし、メソッドが例外をスローする場合は、より複雑になります。addExceptiontry/catchブロックとメソッドが必要になります。

于 2010-05-22T06:22:29.910 に答える