これは基本的な OO です。達成しようとしているもの (データの読み込み) を、達成するために使用しているメカニズム (データベース クエリまたは Web サービス呼び出し) から抽象化する必要があります。
このような設計には、通常、実行できることのコントラクトを定義するインターフェイスと、実装に従ってそれを実現する複数の実装クラスが含まれます。
たとえば、次のようなインターフェイスになります。
public interface DataLoader
{
public Collection<Data> loadData() throws DataLoaderException;
}
次にJdbcDataLoader
、WebServiceDataLoader
、 などの実装があります。あなたの場合、 の 1 つ以上のインスタンスを指定して実行しDataLoader
、結果を合計して集計する別のタイプの実装が必要になります。この実装は次のようになります。
public class AggregatingDataLoader implements DataLoader
{
private Collection<DataLoader> dataLoaders;
private ExecutorService executorService;
public AggregatingDataLoader(ExecutorService executorService, Collection<DataLoader> dataLoaders)
{
this.executorService = executorService;
this.dataLoaders = dataLoaders;
}
public Collection<Data> loadData() throws DataLoaderException
{
Collection<DataLoaderCallable>> dataLoaderCallables = new ArrayList<DataLoaderCallable>>();
for (DataLoader dataLoader : dataLoaders)
{
dataLoaderCallables.add(new DataLoaderCallable(dataLoader));
}
List<Future<Collection<Data>>> futures = executorService.invokeAll(dataLoaderCallables);
Collection<Data> data = new ArrayList<Data>();
for (Future<Collection<Data>> future : futures)
{
add.addAll(future.get());
}
return data;
}
private class DataLoaderCallable implements Callable<Collection<Data>>
{
private DataLoader dataLoader;
public DataLoaderCallable(DataLoader dataLoader)
{
this.dataLoader = dataLoader;
}
public Collection<Data> call()
{
return dataLoader.load();
}
}
}
これにタイムアウトと例外処理ロジックを追加する必要がありますが、要点はわかります。
DataLoader
もう 1 つの重要な点は、テスト中にさまざまな実装を交換したり、モックを使用したりできるように、呼び出しコードでインターフェイスのみを使用する必要があることです。