views:

128

answers:

2

Hi,

I'm writing a small chat program in Java. I got some classes whose objects have to keep track of one another (e.g. the connection listener needs to update the GUI when a new message comes in, just like the GUI needs to write to the connection's writer, when the user wants to send a message).

In Cocoa on Mac OS X I'd write & implement a delegate model. What about in Java? (So far, I'm just passing 'this' as an argument when I initialize a new object, in order to keep a reference to it from the new object.)

Thanks, B

A: 

Delegates are not directly provided by the Java language; using a listener pattern is the closest that standard Java comes to delegates.

However, I have implemented callback/delegate support in Java using reflection. Details and working source are available on my website.

How It Works

We have a principle class named Callback with a nested class named WithParms. The API which needs the callback will take a Callback object as a parameter and, if neccessary, create a Callback.WithParms as a method variable. Since a great many of the applications of this object will be recursive, this works very cleanly.

With performance still a high priority to me, I didn't want to be required to create a throwaway object array to hold the parameters for every invocation - after all in a large data structure there could be thousands of elements, and in a message processing scenario we could end up processing thousands of data structures a second.

In order to be threadsafe the parameter array needs to exist uniquely for each invocation of the API method, and for efficiency the same one should be used for every invocation of the callback; I needed a second object which would be cheap to create in order to bind the callback with a parameter array for invocation. But, in some scenarios, the invoker would already have a the parameter array for other reasons. For these two reasons, the parameter array did not belong in the Callback object. Also the choice of invocation (passing the parameters as an array or as individual objects) belongs in the hands of the API using the callback enabling it to use whichever invocation is best suited to it's inner workings.

The WithParms nested class, then, is optional and serves two purposes, it contains the parameter object array needed for the callback invocations, and it provides 10 overloaded invoke() methods (with from 1 to 10 parameters) which load the parameter array and then invoke the callback target.

Software Monkey
+3  A: 

In Cocoa/Objective-C, delegates are objects that adhere to a specified protocol. A Java interface is analogous to an Objective-C protocol, except that Java does not permit optional methods: if your class implements an interface, you must implement all of the methods.

If you're cool with all of a delegate's methods being required, simply define an interface and use that.

If your delegate interface has a lot of methods and it would be convenient to make some of them optional, you could define an Adapter class that implements the delegate interface, providing a default implementation for each of the methods. To use it, your delegate class must either extend the adapter class or, if that is not possible, define a private inner class that extends the adapter class. (Look at Java's MouseListener interface and MouseAdapter class for an example of this.)

In summary, you can still use the delegate pattern in Java, although the static type checking will make optional methods a little more work.

benzado