私のコードベースには、次のようなパターンがあります。キューからのメッセージを処理し、そのメッセージを次のキューに渡します。これまでの使用例は、同じタイプのメッセージを処理して生成することでした。
public interface Processor<T> {
T process(T thing);
}
そのユースケースは、異なるタイプの処理と生成に進化しました。さらに、1つのタイプを処理して、他のタイプを生成する必要がある場合があります。
したがって、次のようなもの:
public interface NewProcessor<I, O> {
O process(I thing;)
}
そして将来的にはおそらく次のようなものが必要になるでしょう
public interface FutureProcessor<I, O1, O2> { //potentially N number of O
Pair<O1, O2> process(I thing);
}
私の質問は、次のとおりです。3つの個別のクラスを使用するよりも、このクリーンな方法を表現する方法はありますか?ここで使用できる素敵な既知の階層はありますか?
新しいプロセッサを追加するたびに書き直す必要がないようにしたい最初のタイプのプロセッサの抽象的なユーザーがいます。それは今日このようなことをします:
public abstract AbstractModule<T> {
private Processor<T> processor;
public AbstractModule(Processor<T> processor) {
this.processor = processor;
}
T runModule(T input) {
// abstract validateInput(input);
T result = processor.process();
// record results
return result;
}
}
これを行う方法に関する既知のパターンまたは提案があれば幸いです!
おそらくデコレータパターンのようなものを適用できます。これにより、1つのインターフェースを持つことができます。たとえば、Java.util.Function
、ただし、入力と出力の中間変換ステップを簡単に導入できます。
class Decorator<I, O, D> implements Function<I, D>
{
private final Function<I, O> function;
private final Function<O, D> delegate;
public Decorator( Function<I , O> function, Function<O, D> delegate )
{
this.function = function;
this.delegate = delegate;
}
@Override
public D apply( I input )
{
O output = function.apply( input );
return delegate.apply( output );
}
}
次に、文字列を整数に変換し、文字列を変更してから、整数に戻す簡単な例を示します。
@Test
public void testDelegate()
{
Function<Integer, String> intToString = String::valueOf;
Decorator<Integer, String, String> repeatString = new Decorator<>(
intToString, s -> s + s );
assertEquals( "33", repeatString.apply( 3 ));
Decorator<Integer, String, Integer> repeatThenToInt = new Decorator<>(
repeatString, Integer::valueOf );
assertEquals( 33, repeatThenToInt.apply( 3 ).intValue() );
}