views:

324

answers:

8

I have a couple of classes that want to pass each other some information and be called back later, using that information (Callback pattern).

Within my application, this mechanism serves two purposes:

  • scheduled / delayed execution
  • asynchronous execution involving messaging

My objects basically say to each other "when you're finished doing X, call me back and tell me to do Y with Z (because I'll have forgotten about it by then)". Where X might just be waiting for the right time, but also communicating with a remote service or calling a local function.

Now, were there function pointers (or equivalent) in Java, I would implement some "Job" class containing one plus the arguments it needs. For example, in PHP this structure would have to store a class name, a function name and an array of arguments. In C, it would be a pointer to the function and I'd have to make the arguments the same number and type for all calls.

In Java, the usual approach is to have an interface that's implemented by all classes that want to be called back, like this:

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

Now this wouldn't work for me, because

  • the objects to be called back might have a different set of methods to take the call
  • the caller is not the one to decide what call should be made

Maybe my problem is that I'm trying to have a common data structure and calling procedure for the various callbacks, but in principle, it seems to make sense to me.

What's a good design pattern to approach this situation in Java?

A: 

I may be misunderstanding the problem, but it seems to me you would benefit from setting up some sort of event system.

Basically you set up an event handler and the classes that would like to know about the event subscribe to the event handler. So for your problem, when X is done it would fire a FinishedProcessingEvent() which your object would be subscribed to. When your object receives this event (along with any other subscribers who care about the event) it will do the proper action (Y with Z). These actions are defined within the objects so different objects could do different things based on the same events.

Does this help?

kgrad
+6  A: 

I think you'll find that an Interface is the best solution. I don't understand your objection to them. If the receiver needs to have a different method called, then have the Interface method call the different method.

If your receiver class needs to have multiple handlers, you can use anonymous inner classes that implement the Interface, one for each type of handler you need. For instance, if the sender uses an interface called "ListenerInterface", your receiver might define an anonymous inner class that implements the ListenerInterface and calls the receiver method "handlerFunction".

   sender.addListener(new ListenerInterface()
   {
      public void callback(Object arg)
      {
         handlerFunction(arg);
      }
   });
Paul Tomblin
That last sentence sounds promising - but I think I haven't quite understood it (sorry, I'm new to Java - it seems anonymous inner classes are used often, but so far, I didn't get them). More specifically, would these classes be inside the caller or the callee? Could you expand a little, please?
Hanno Fietz
That link sfossen posted below helped already.
Hanno Fietz
I've tried to expand my answer a bit.
Paul Tomblin
Thanks. This concept is very new to me, I'm not sure why. Is it quite specific for Java development?
Hanno Fietz
Perl has anonymous "subs" which are similar to an anonymous inner class in a way. Other than that, I've never encountered them before.
Paul Tomblin
A: 

I am sure there is some interesting pattern that solves your problem, but I would choose the simple minded approach using infrastructure. Stuffing requests and responses in a message queue, like JMS, your system might be simpler and more robust because you could handle events taking seconds or weeks without worrying about system restarts, persistence and message integrity.

A: 

I haven't looked too much into it, but the Java 5+ Future interface (or its sub-interfaces) might be useful for this.

R. Bemrose
+2  A: 

I would use an interface, as you've described, and then use an anonymous class for your callbacks. For example, from inside your caller:

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

(The syntax may be slightly different than that.)

That way you can specify in the original caller (at the point of the call) which action to take when finished.

Jesse Rusak
What does the "this" prepended in front of the invocation of actionToCall(data) do?
Steve Kuo
+1  A: 

Callbacks are a general idea and you shouldn't attempt a one-size-fits-all interface. Make your callback interface specific to the use. It should match the semantics of the type that it is passed to and that does the calling back. The usual implementation of the callback interface would be done as an anonymous inner class. Resist the temptation to implement the interface in an outer class resulting in an incoherent type.

Tom Hawtin - tackline
+3  A: 

You could be using a concept similar to anonymous inner classes

Another reference here

sfossen
Thanks, that link helped me to make more of Paul Tomblin's answer.
Hanno Fietz
@Hanno Fietz: glad it helped, I've added another reference which may be more helpful.
sfossen
Thanks to you, too. As I already commented above: This concept is very new to me, I'm not sure why. Is it quite specific for Java development?
Hanno Fietz
I see Paul answered in his comments :P
sfossen
+1  A: 

If you really don't want to use interfaces (and trust me you do!) you could use reflection to get the method you want to have called and then pass it to the one that needs to do the calling. This is as close to a C function pointer as you are going to get.

Reflection will be slower (probably) than the interface way of doing it (but that won't matter unless it is called frequently).

Reflection will not have the compile time type checking that the interface way of doing it has (which means you could crash at runtime).

Reflection will be uglier code than the interface way of doing it as well.

But if you really really really want to simulate C function pointers then reflection is as close as you are going to get.

TofuBeer