嵌套回调的Java模式?

And*_*wan 42 java design-patterns asynchronous nested callback

我正在寻找一种Java模式来制作嵌套的非阻塞方法调用序列.在我的例子中,一些客户端代码需要异步调用服务来执行某些用例,并且该用例的每个步骤本身必须异步执行(出于此问题范围之外的原因).想象一下,我现有的接口如下:

public interface Request {} 

public interface Response {} 

public interface Callback<R extends Response> {
    void onSuccess(R response);
    void onError(Exception e);
}
Run Code Online (Sandbox Code Playgroud)

RequestResponse接口的各种配对实现,即RequestA+ ResponseA(由客户端给出),RequestB+ ResponseB(由服务内部使用)等.

处理流程如下所示:

显示嵌套回调的序列图.

在接收到每个响应和发送下一个请求之间,需要进行一些额外的处理(例如,基于任何先前请求或响应中的值).

到目前为止,我已经尝试了两种在Java中编码的方法:

  • 匿名类:由于所需的嵌套而很快变得难看
  • 内部类:比上面更整洁,但仍然难以让其他开发人员理解执行流程

是否有一些模式可以使这些代码更具可读性?例如,我可以将服务方法表示为一个自包含操作的列表,这些操作由一些负责嵌套的框架类按顺序执行吗?

Rob*_*b I 13

由于实现(不仅是界面)不能阻止,我喜欢你的列表想法.

设置一个"操作"列表(可能是Futures?),设置应该非常清晰和可读.然后在收到每个响应时,应该调用下一个操作.

有点想象力,这听起来像责任链.这是我想象的一些伪代码:

public void setup() {
    this.operations.add(new Operation(new RequestA(), new CallbackA()));
    this.operations.add(new Operation(new RequestB(), new CallbackB()));
    this.operations.add(new Operation(new RequestC(), new CallbackC()));
    this.operations.add(new Operation(new RequestD(), new CallbackD()));
    startNextOperation();
}
private void startNextOperation() {
    if ( this.operations.isEmpty() ) { reportAllOperationsComplete(); }
    Operation op = this.operations.remove(0);
    op.request.go( op.callback );
}
private class CallbackA implements Callback<Boolean> {
    public void onSuccess(Boolean response) {
        // store response? etc?
        startNextOperation();
    }
}
...
Run Code Online (Sandbox Code Playgroud)


Dan*_*den 7

在我看来,模拟这类问题的最自然方式是Future<V>.

因此,不要使用回调,只需返回一个"thunk":a Future<Response>表示将来某个时候可用的响应.

然后,您可以根据需要对后续步骤进行建模Future<ResponseB> step2(Future<ResponseA>),或者ListenableFuture<V>从Guava中使用.然后你可以使用Futures.transform()或其中一个重载以自然的方式链接你的函数,但仍保留异步性质.

如果以这种方式使用,Future<V>表现得像monad(事实上,我认为它可能有资格作为一个,虽然我不确定我的头脑),所以整个过程感觉有点像Haskell中的IO执行通过IO monad.