I'm trying to find the most effective way to, in a generic way, create an implementation of a functional interface that forwards each call on it to a number of instances of that same interface. The goal is to simplify the implementation of interfaces which allow client code to register themselves for multiple events by passing a handler (implemented as a functional interface) to the appropriate registration function. An example:
/** The interface in question we want to implement with minimal effort. */
interface TrainStation {
void onTranArrived(TrainArrivedHandler handler);
void onPassengerArrived(PassengerArrivedHandler handler);
interface TrainArrivedHandler {
void apply(String track, String lineNumber);
}
interface PassengerArrivedHandler {
void apply(String track);
}
}
This may be one example of such an interface. There would be many such interfaces, each with different events, so the implementation should be as simple as possible, without much duplicate code. I imagine that this may best be possible by introducing a type Event
for internal use in such an implementation, which allows forwarding events to all registered handlers:
/** Used in an implementation to implement on*() functions. */
interface Event<HANDLER> {
/** Register a handler. */
void on(HANDLER handler);
/** Signal all registered handlers. */
HANDLER getMasterHandler();
static <HANDLER> Event<HANDLER> create() {
// Magic. May need an instance of Class<HANDLER>, which is okay.
}
}
An implementation of TrainStation
could then look like this:
final class TrainStationImpl implements TrainStation {
private final Event<TrainArrivedHandler> trainArrivedEvent = Event.create();
private final Event<PassengerArrivedHandler> passengerArrivedEvent = Event.create();
@Override
public void onTranArrived(TrainArrivedHandler handler) {
trainArrivedEvent.on(handler);
}
@Override
public void onPassengerArrived(PassengerArrivedHandler handler) {
passengerArrivedEvent.on(handler);
}
/** Generates some events. */
public void makeSomethingHappen() {
trainArrivedEvent.getMasterHandler().apply("34", "S12");
passengerArrivedEvent.getMasterHandler().apply("2"); // Wants to catch the S12, but is obviously too late now.
}
}
This is a manageable level of required code. The bulk of it can be extracted to an abstract class and thus is only necessary once per interface. Of course, any way to reduce it is a plus but I can't see a straightforward way without exposing the Event
instances.
Going forward with this approach, the interesting thing is the implementation of the interface Event
. I can certainly imagine doing it with plain old reflection, which has acceptable but not really outstanding performing. But I reckon that there should be a more efficient and/or more straight-forward way to implement the return value of Event.getMasterHandler()
using the APIs added in Java 1.7, especially MethodHandle
, since we know that each handler interface is a functional interface. How would I go about doing this?
Aucun commentaire:
Enregistrer un commentaire