Java 使用回调而不是返回状态对象

Java 使用回调而不是返回状态对象,java,callback,design-patterns,listener,Java,Callback,Design Patterns,Listener,在我的应用程序中,我正在执行一个事务,该事务在执行结束时可能处于三种不同的状态: 成功 失败 悬而未决的 根据状态的不同,应用程序客户端将希望执行不同的操作。如果成功,他们将希望通过小部件检索事务结果。在失败的情况下,他们将希望收到错误原因。在事务挂起的情况下,他们将希望安排重试时间。当前,我使用以下方法返回一个对象: public interface Result() { State getState(); Widget getWidget(); // Success

在我的应用程序中,我正在执行一个事务,该事务在执行结束时可能处于三种不同的状态:

成功 失败 悬而未决的 根据状态的不同,应用程序客户端将希望执行不同的操作。如果成功,他们将希望通过小部件检索事务结果。在失败的情况下,他们将希望收到错误原因。在事务挂起的情况下,他们将希望安排重试时间。当前,我使用以下方法返回一个对象:

public interface Result() {
     State getState();
     Widget getWidget(); // Success
     Reason getFailureReason(); // Failure
     Callable<Result> getTask(); // Pending
}
我在想,使用回调可能更可取,例如

public interface TransactionCallback() {
    void onFailure(Reason reason);
    void onSuccess(Widget widget);
    Delay onPending(Delay previous);
}
其中Delay是一个表示时间和周期的类,允许应用程序重新安排事务执行。另一种选择是抛出一个包含失败原因的异常,因为它只应在异常情况下失败,并保留onSuccess和onPending方法


因此,我对So的问题是:使用回调是解决这个特定问题的合适模式,还是有人能提出更合适的建议?

我更喜欢回调,因为如果在多个地方使用回调,会导致代码更少,可读性更高。通过回调您的if语句来确定将要发生什么,调用哪个方法将在执行事务的服务中,并且使用该服务的所有代码将看起来更干净。

我更喜欢回调,因为如果在多个位置使用它,将导致代码更少,可读性更高。使用回调if语句来确定将要发生什么,调用哪个方法将在执行事务的服务中,使用该服务的所有代码看起来都更干净。

回调参数应该包括调用的对象。听起来不错,但是使用回调可能会涉及一些同步问题-您无法确定在哪个状态下接收回调。并非不可能,但可能需要考虑


当然,对于轮询结果,您需要在另一端进行同步。但这听起来更容易同步。

回调参数应该包括调用的源对象。听起来不错,但是使用回调可能会涉及一些同步问题-您无法确定在哪个状态下接收回调。并非不可能,但可能需要考虑


当然,对于轮询结果,您需要在另一端进行同步。但这听起来更容易同步。

回调解决方案具有更大的可扩展性,而您可能在某一点上希望将行为更改为异步调用


缺点是您的代码可读性较差,特别是对于那些初学者程序员。如果这对你来说不是问题那么当然,继续

回调解决方案具有很强的可扩展性,而您可能在某一点上希望将行为更改为异步调用


缺点是您的代码可读性较差,特别是对于那些初学者程序员。如果这对你来说不是问题那么当然,继续

我认为这不是回调模式的好用法

如果被调用方(例如,您案例中的事务)需要在回调方法返回后继续执行操作,则回调是合适的。但是如果被调用者总是做的下一件事是返回调用者,那么回调不会增加任何值。这只会使代码结构更复杂,可读性更低。在我看来,最好返回一个result对象,或者在异常失败的情况下抛出一个异常

编辑-重新编辑OP的评论


我可以看到使用回调方法询问调用者事务是否应该继续的价值,尽管我可能会使用一个简单的超时参数。但是,使用回调方法返回结果仍然是错误的。

我认为这不是回调模式的好用法

如果被调用方(例如,您案例中的事务)需要在回调方法返回后继续执行操作,则回调是合适的。但是如果被调用者总是做的下一件事是返回调用者,那么回调不会增加任何值。这只会使代码结构更复杂,可读性更低。在我看来,最好返回一个result对象,或者在异常失败的情况下抛出一个异常

编辑-重新编辑OP的评论


我可以看到使用回调方法询问调用者事务是否应该继续的价值,尽管我可能会使用一个简单的超时参数。但是,使用回调方法返回结果仍然是错误的。

回调不是异步的,因此我不确定您的问题在这种情况下是否有效。但是如果您在单独的线程中运行工作负载,它可能是异步的。void方法和回调的一个好处是,您可以随时将工作分派到单独的线程。无论如何,即使是同步返回,您也可以

除非锁定对象,否则在获取返回值时无法确定对象的状态。我认为这两种情况下都会带来更好的设计。但是,该对象可能会作为接口的参数包含在内,或者您必须在接收方对象中设置一些状态,以便它知道结果来自何处。如果可能的话,应该避免添加更多的状态。最终用户将无法看到事务,因此我不确定传回该对象是否会对最终用户有很大帮助。我还一直在考虑最终用户可以用来识别特定操作的handback对象的用户。@kyoryu:也许是时候让我在实践中回到并发性上来了;回调不是异步的,所以我不确定您的关注点在这种情况下是否有效。但是如果您在单独的线程中运行工作负载,它可能是异步的。void方法和回调的一个好处是,您可以随时将工作分派到单独的线程。无论如何,即使使用同步返回,在获取返回值时也无法确定对象的状态,除非锁定对象。我认为这两种情况下都会带来更好的设计。但是,该对象可能会作为接口的参数包含在内,或者您必须在接收方对象中设置一些状态,以便它知道结果来自何处。如果可能的话,应该避免添加更多的状态。最终用户将无法看到事务,因此我不确定传回该对象是否会对最终用户有很大帮助。我还一直在考虑最终用户可以用来识别特定操作的handback对象的用户。@kyoryu:也许是时候让我在实践中回到并发性上来了;同意。我发现我使用的无效方法和回调越多,代码就越干净。如果没有单独的对象,那么将发出请求、处理结果和处理错误分离到单独的方法中似乎会产生更干净、更易于维护的代码。我发现我使用的无效方法和回调越多,代码就越干净。如果没有单独的对象,将发出请求、处理结果和处理错误分离到单独的方法中似乎会产生更干净、更易于维护的代码。但情况并非总是这样:如果事务处于挂起状态,则事务将保持轮询,直到事务成功或失败。onPending方法的返回需要知道等待到下一次轮询的时间。我喜欢通过超时来完全消除挂起情况的想法,尽管请求之间的时间可能不一定相等,但我不太相信您不愿意使用回调。你有什么证据支持你的观点吗?我同意斯蒂芬的观点。在这种情况下,回调只会使代码更难理解。我理解让代码可扩展的愿望,但是牺牲可读性,就牺牲了可维护性。我认为更有可能的是,有一天,另一个程序员会比你更不理解代码,并利用回调增加的可扩展性制造混乱。@David-我的参考是常识。只要比较这两种实现方式的代码量/复杂性,你就会发现它们的不同。但情况并非总是如此:如果事务处于挂起状态,则事务将一直轮询,直到事务成功或失败。onPending方法的返回需要知道等待到下一次轮询的时间。我喜欢通过超时来完全消除挂起情况的想法,尽管请求之间的时间可能不一定相等,但我不太相信您不愿意使用回调。你有什么证据支持你的观点吗?我同意斯蒂芬的观点。在这种情况下,回调只会使代码更难理解。我理解让代码可扩展的愿望,但是牺牲可读性,就牺牲了可维护性。我认为更有可能的是,有一天,另一个程序员会比你更不理解代码,并利用回调增加的可扩展性制造混乱。@David-我的参考是常识。只要比较这两种实现方法的代码量/复杂性,您就会看到差异。
public interface TransactionCallback() {
    void onFailure(Reason reason);
    void onSuccess(Widget widget);
    Delay onPending(Delay previous);
}