0

我有几个类想要相互传递一些信息并在以后使用该信息(回调模式)被回调。

在我的应用程序中,这种机制有两个目的:

  • 计划/延迟执行
  • 涉及消息传递的异步执行

我的对象基本上互相说“当你完成 X 后,给我回电话并告诉我用 Z 做 Y(因为到那时我会忘记它)”。X 可能只是在等待正确的时间,但也与远程服务通信或调用本地函数。

现在,如果 Java 中有函数指针(或等价物),我会实现一些“作业”类,其中包含一个加它需要的参数。例如,在 PHP 中,这个结构必须存储一个类名、一个函数名和一个参数数组。在 C 中,它是一个指向函数的指针,我必须为所有调用设置相同的参数编号和类型。

在 Java 中,通常的方法是拥有一个由所有想要回调的类实现的接口,如下所示:

public interface ICallable {
    public void call_me(Object data);
}

现在这对我不起作用,因为

  • 要回调的对象可能有一组不同的方法来进行调用
  • 呼叫者不是决定应该拨打什么电话的人

也许我的问题是我试图为各种回调建立一个通用的数据结构和调用过程,但原则上,这对我来说似乎很有意义。

在 Java 中处理这种情况的好的设计模式是什么?

4

8 回答 8

6

我想你会发现接口是最好的解决方案。我不明白你对他们的反对。如果接收者需要调用不同的方法,则让接口方法调用不同的方法。

如果您的接收器类需要有多个处理程序,您可以使用实现接口的匿名内部类,一个用于您需要的每种类型的处理程序。例如,如果发送方使用名为“ListenerInterface”的接口,您的接收方可能会定义一个匿名内部类来实现 ListenerInterface 并调用接收方方法“handlerFunction”。

   sender.addListener(new ListenerInterface()
   {
      public void callback(Object arg)
      {
         handlerFunction(arg);
      }
   });
于 2009-03-09T15:31:59.707 回答
3

您可能正在使用类似于匿名内部类的概念

这里的另一个参考

于 2009-03-09T15:41:42.990 回答
2

正如您所描述的,我将使用一个接口,然后为您的回调使用一个匿名类。例如,从您的调用者内部:

ICallback callback = new ICallback() { 
    public void call_me(Object data) { this.actionToCall(data); }
}
serverObject.doX(callback);

(语法可能与此略有不同。)

这样,您可以在原始调用者(在调用点)中指定完成后要采取的操作。

于 2009-03-09T15:38:24.107 回答
2

如果您真的不想使用接口(相信我,您会这样做!),您可以使用反射来获取您想要调用的方法,然后将其传递给需要调用的方法。这与您将要获得的 C 函数指针一样接近。

反射将(可能)比执行它的接口方式慢(但这并不重要,除非它被频繁调用)。

反射不会像接口方式那样进行编译时类型检查(这意味着您可能会在运行时崩溃)。

反射也将是比接口方式更丑陋的代码。

但是,如果您真的真的很想模拟 C 函数指针,那么反射就像您将要获得的一样接近。

于 2009-03-09T17:00:50.880 回答
1

回调是一个普遍的想法,您不应该尝试一刀切的接口。使您的回调接口特定于使用。它应该与传递给它并进行回调的类型的语义相匹配。回调接口的通常实现将作为匿名内部类完成。抵制在外部类中实现接口的诱惑,从而导致类型不连贯。

于 2009-03-09T15:41:18.170 回答
0

我可能误解了这个问题,但在我看来,你会从设置某种事件系统中受益。

基本上,您设置了一个事件处理程序,并且想要了解该事件的类订阅该事件处理程序。因此,对于您的问题,当 X 完成时,它将触发您的对象将订阅的 FinishedProcessingEvent()。当您的对象收到此事件(以及关心该事件的任何其他订阅者)时,它将执行正确的操作(Y 与 Z)。这些动作是在对象中定义的,因此不同的对象可以基于相同的事件做不同的事情。

这有帮助吗?

于 2009-03-09T15:30:55.823 回答
0

我确信有一些有趣的模式可以解决您的问题,但我会选择使用基础设施的简单方法。将请求和响应填充到消息队列(如 JMS)中,您的系统可能会更简单、更健壮,因为您可以处理耗时数秒或数周的事件,而无需担心系统重启、持久性和消息完整性。

于 2009-03-09T15:32:06.197 回答
0

我没有过多研究它,但 Java 5+ Future接口(或其子接口)可能对此有用。

于 2009-03-09T15:34:03.477 回答