In the following, I want EventHandler to handle EventA one way, EventB another way, and any other Events (EventC, EventD) yet another way. EventReceiver receives only a reference to an Event and calls EventHandler.handle(). The version that always gets called, of course, is EventHandler.handle(Event event).
Without using instanceOf, is there a way to polymorphically dispatch (perhaps via another method in EventHandler or generics) to the appropriate handle method?
class EventA extends Event {
}
class EventB extends Event {
}
class EventC extends Event {
}
class EventD extends Event {
}
class EventHandler {
void handle(EventA event) {
System.out.println("Handling EventA");
}
void handle(EventB event) {
System.out.println("Handling EventB");
}
void handle(Event event) {
System.out.println("Handling Event");
}
}
class EventReceiver {
private EventHandler handler;
void receive(Event event) {
handler.handle(event);
}
}
A Dispatcher is used to build an application by aggregating several services. The dispatcher maintains a registry of Service objects. A Service is categorized by the type of processing it performs: A pre-processing service pre-processes input data for the command being processed.
Dynamic method dispatch is the mechanism in which a call to an overridden method is resolved at run time instead of compile time. This is an important concept because of how Java implements run-time polymorphism.
Dynamic method dispatch is the mechanism by which a call to an overridden method is resolved at run time, rather than compile time.
Double dispatch is a technical term to describe the process of choosing the method to invoke based both on receiver and argument types. A lot of developers often confuse double dispatch with Strategy Pattern. Java doesn't support double dispatch, but there are techniques we can employ to overcome this limitation.
Sounds like a case for applying (a variant of) the Visitor pattern. (In mainstream OO languages such as C++, C# and Java, methods are single dispatch, i.e. can only be polymorphic on one type at a time. Visitor allows one to implement double dispatch.)
This however requires that you be able to modify the Event
classes as well, and creates a dependency from Event
s to (a base interface of) EventHandler
.
class EventA extends Event {
public handleBy(EventHandler eh) {
eh.handleEventA(this);
}
}
class EventB extends Event {
public handleBy(EventHandler eh) {
eh.handleEventB(this);
}
}
class EventHandler {
void handleEventA(EventA event) {
System.out.println("Handling EventA");
}
void handleEventB(EventB event) {
System.out.println("Handling EventB");
}
void handle(Event event) {
event.handleBy(this);
}
}
This is a use case for double-dispatch, no (which as one may indeed know is either called Visitor) ? I'll implement your example for EventA only
class Event {
/**
* Will do some type escalation
*/
void handleWith(EventHandler care) {
care.handle(this);
}
}
class EventA extends Event {
/**
* As event is EventA, this implementation is called, with its correct type forced by the cast
*/
void handleWith(EventHandler care) {
care.handle((EventA) this);
}
}
class EventHandler {
/**
* Finally comes here
*/
void handle(EventA event) {
System.out.println("Handling EventA");
}
void handle(EventB event) {
System.out.println("Handling EventB");
}
void handle(Event event) {
System.out.println("Handling Event");
}
/**
* Go here first and dispatch call to Event class
*/
void doHandle(Event event) {
event.handleWith(this);
}
}
class EventReceiver {
private EventHandler handler;
void receive(Event event) {
handler.doHandle(event);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With