web-dev-qa-db-ja.com

実装が一般的でない場合のインターフェースでのジェネリックの使用

実装がジェネリックにならないときに、ジェネリックをインターフェイスに配置することは許容できる方法ですか?私のプロジェクトに、データベースからデータを読み取る多くのクラスがあるとしましょう。私は次のような一般的なインターフェイスを作成できます:

public interface DataRetriever<T, R>{

  R retrieveData(T criteria);

}

public class UserDataRetriever implements DataRetriever<UserCriteria, User>{

  @Override
  public User retrieveData(UserCriteria criteria) {
    ...
  }
}

または、次の例も考えられます。

public interface DataRetriever2<R>{

  R retrieveData();

}
public class UserDataRetriever2 implements DataRetriever2<User>{

  @Override
  public User retrieveData() {
    ...
  }
}

インターフェイスにジェネリックスがあると、インターフェイスの再利用性が大幅に向上し、データ取得クラスごとに1つのインターフェイスが不要になるようです。ただし、インターフェイスのドキュメントが曖昧にならざるを得ないという懸念があります。また、retrieveDataメソッドのパラメーターの数を守る必要があるため、シナリオ1の新しいpojoオブジェクトを作成したり、シナリオ2のコンストラクターにすべてを配置せざるを得なかったりする可能性があります。ジェネリックを使用しますか?

2
radian

ジェネリックインターフェイスのジェネリック以外の実装は、それを示した方法と同じであり、何も問題はありません。

しかしもちろん、優れた汎用インターフェースを設計することは、特定のインターフェースよりも大きな課題です。したがって、DataRetrieverインスタンスがどうなるか、そしてそれが役立つためにサポートする必要がある操作を決定する必要があります。単一のDataRetrieverインスタンスが、特定のクラスのすべてのクエリを管理することを期待します。 User、(しかし、それはあなたが考えていることではないかもしれません...)。

次に、R retrieveData(T criteria)は私にとって便利な操作のように見えますが、R retrieveData()はクエリ基準を指定する方法がありません。

また、QueryCriteriaのジェネリックインターフェイスを導入し、Tを拡張してQueryCriteria<R>にすることもできます。そのため、すべての実装は、オブジェクトタイプと一致する基準を想定しています。

また、retrieveDataメソッドのパラメーターの数を順守する必要があるため、シナリオ1の新しいpojoオブジェクトを作成したり、シナリオ2のコンストラクターにすべてを強制的に配置したりできます。

関数シグネチャの順守は、インターフェイスを使用する上での核心部分なので、同僚が回避策に強制的に戻らないように定義します。それ以外の場合は、インターフェイスを再考する必要があります。したがって、分析の結果、データ取得に必要なのは単一の基準オブジェクトだけである場合は、そのパターンに固執します(さまざまな実装に必要な基準クラスを定義させます)。

3
Ralf Kleberhoff