您的用例是获取一个对象,对其进行处理并生成一个新对象。基本上是一个参数的函数。我认为关键部分是参数的数量,因为您只能在Java中返回一个结果。如果您确定将来不再需要一次处理多个对象,那么就没有比使用已经定义的函数更通用的方法了(我会在JDK中使用不过,在这种情况下,Function
和UnaryOperator
)是可能的。
假设您要继续使用自定义函数,并且不想像您所说的那样更改AbstractModule
。我至少将Processor
重命名为UnaryProcessor
。然后,我将其更改如下:
public interface Processor<T,R> {
R process(T t);
}
public interface UnaryProcessor<T> extends Processor<T,T> {}
这时,您将能够处理您提到的Processor<T,Pair<O1,O2>>
的上一个用例。相同的逻辑适用于任何将来的用例,您只需要用当时需要的任何类型(例如List<E>
)来替换返回类型。
,
与其从方法调用中返回结果,不如对每个处理器可能从输入生成的结果进行回调,以初始化每个处理器。
这非常适合队列处理应用程序,因为回调可能会为其他队列生成一条新消息,并且您可以轻松拦截结果以执行诸如监视之类的事情,而无需修改处理器。
interface Processor<T> {
void process(T message);
}
interface Output<T> {
result(T result);
}
class SomeKindOfProcessor implements Processor<SomeInput> {
private final Output<? super Foo> foo;
private final Output<? super Bar> bar;
// These parameters are probably injected by some sort of IoC container.
// They are easy to mock in tests too,so you can unit test this
// class in isolation.
SomeKindOfProcessor(Output<? super Foo> foo,Output<? super Bar> bar) {
this.foo = foo;
this.bar = bar;
}
@Override
public void process(SomeInput input) {
/* Do some work that results in a Bar instance */
bar.result(new Bar(...));
/* Do some more work that might result in a Foo instance. */
if (...) {
foo.result(new Foo(...));
}
}
}
如果回调实现需要将结果与输入相关联,则通常可以使用输入中的一些标识符来实现。
,
您的输出结果可能是抽象的,您总是将其返回
class Result<T1,T2,T3>{// only change Result class
boolean hasType1 //no need to change method interface that returns Result
boolean hasType2
boolean hasType3
T1 t1
T2 t2
T3 t3
// you can use other implementation such as array...
}
public interface Processor<T> {//only one interface that always returns Result
Result process(T thing);
}
,
您不必保持处理器功能接口采用多个输入和/或输出,而是将其保持不变,而是使用汇总的输入和/或输出。
您应该优先为集合命名一个有用的名称,因为一对整数可能例如根据这些int表示什么而称为Vertex,Point,Dimension等。仅当您的聚合没有有用的名称并且您不打算在其他地方使用它时,才可以使用诸如ProcessInput或ProcessOutput之类的通用名称。
agreget示例:
class Vertex {
final public int x;
final public int y;
public Vertex(int x,int y) {
this.x = x;
this.y = y;
}
}
我通常更喜欢将字段保留在这样一个汇总的final中,以使时间不变,但是没有什么要求您这么做。
就像其他建议的那样,可以创建通用聚合。不要以为您需要这样做。我通常更喜欢带有上帝有用名称的聚合,并且其中单个成员字段或属性也可以具有良好的有用名称。必须记住,第三个整数是计数,第二个String是名称,这可能导致代码不那么容易阅读。
,
也许您可以应用装饰器模式之类的东西。这将使您拥有一个界面,例如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,Integer> repeatThenToInt = new Decorator<>(
repeatString,Integer::valueOf );
assertEquals( 33,repeatThenToInt.apply( 3 ).intValue() );
}
本文链接:https://www.f2er.com/2423697.html