I'm currently implementing asynchronous-like event queue inside my application - it is designed to work like this: one component reacts to some user input and putting event to the queue, and another "listener" is checking whether there is event of specific type inside the queue and run it's own business logic
There can be various event types (like USER_MOUSE_CLICK, USER_KEYBOARD_CLICK etc) and every implementation has it's own "event-object" type
It looks like this (I'm ommiting constructors - setting all fields and getters/setters - they are just normal default ones):
public abstract MyEvent<T> {
private EventType eventType;
private T eventData;
}
public MouseClickEvent extends MyEvent<ClickPoint> { // ClickPoint class contains x,y of mouse click
public MouseClick(ClickPoint point) {
super(EventType.USER_MOUSE_CLICK, point);
}
}
public KeyboardClickEvent extends MyEvent<String> { // character that has been clicked on keyboard
public MouseClick(String key) {
super(EventType.USER_KEYBOARD_CLICK, key);
}
}
I have also a service with queue of MyEvent instances and the method to retrieve first event of provided EventType if exists - it's look like
...
private List<MyEvent> queue;
...
public MyEvent fetchMyEvent(EventType eventType) {
for(MyEvent event : queue) {
if(event.getEventType().equals(eventType) {
return event;
}
}
return null;
}
...
The problem is that when I'm trying to retrieve the event I need to cast it to specific implementation like
// some listener logic
MouseClickEvent event = (MouseClickEvent ) eventService.fetchMyEvent(EventType.USER_MOUSE_CLICK);
log("The X point of mouse click was: " + event.getEventData().x);
I don't like this casting - I feel like I have no control of a types when I'm fetching events and I see this situation like a 'weak point' and bug generator. Is there any design pattern to avoid this, or should I redesign whole system? Or maybe this is the only way and I should not care
I would suggest you the visitor pattern to avoid cast. You are right casting should be used with precaution.
To use visitor pattern you have to :
first: define the visitor interface:
public interface IEventVisitor {
void visit(MouseClickEvent event);
void visit(KeyboardClickEvent event);
}
Second in your supper class define an absract method accept as:
public abstract MyEvent<T> {
private EventType eventType;
private T eventData;
public abstract void accept(IEventVisitor visitor);
}
Third: implement the method for each subclass as:
public MouseClickEvent extends MyEvent<ClickPoint> { // ClickPoint class contains x,y of mouse click
public MouseClick(ClickPoint point) {
super(EventType.USER_MOUSE_CLICK, point);
}
public void accept(IEventVisitor visitor) {
visitor.visit(this);
}
}
And finally implement your visitor interface.
The use will be like the following, instantiate the visitor and call event.accept(visitor).
Event event = eventService.fetchMyEvent(EventType.USER_MOUSE_CLICK);
IEventVisitor visitor = new IEventVisitor() {
#Override
public void visit(MouseClickEvent event) {
// logic goes here
}
#Override
public void visit(KeyboardClickEvent event) {
// logic goes here
}
};
event.accept(visitor);
Related
I have an Event interface, for every Event class implemented, I have a handler. I'm parsing some string and return Event. How can I determine what handler should be invoked using Spring. The main goal to not use if statements, just make it polymorphic. Do you have some examples?
The Strategy Pattern consists of the following components:
An interface common to all specific classes. This is your Event interface.
N concrete classes that implement the interface
A class that maintains a reference to an object whose type is that of your interface and is initialized with an instance of one of the concrete classes.
Therefore, if Strategy is really the pattern you need or want:
public interface Event {
Event handle(String value);
}
public class Event1 implements Event {
Event1 handle(String value) {
//do whatever
}
}
public class Event2 implements Event {
Event2 handle(String value) {
//do whatever
}
}
//etc...
public class StrategyClient {
private Event event;
private String value;
public StrategyClient(Event event){
this.event=event;
}
public Event handle(){
event.handle(value);
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
And so you just need to initialize your StrategyClient with an instance of Event1, or Event2, or any of the classes that implement Event.
In doing some restructuring on a project of mine, I've been attempting to better utilise object oriented concepts in my code but I'm not sure how to structure this particular situation:
A method can trigger one of three possible "events", with each event having a dependency on a particular type (Player, Block, World) which needs to happen at runtime as they are deserialised from a file. In an attempt to simplify the execution path I structured it like this so they can all be part of a List which just executes a single method:
public interface IEvent {
void trigger();
}
public class PlayerEvent implements IEvent {
private Player player;
public void passPlayer(Player player){
this.player = player;
}
public void trigger(){
// player does things
}
}
public class BlockEvent implements IEvent {
private Block block;
public void passBlock(Block block){
this.block = block;
}
public void trigger(){
// block does things
}
}
However, since each event is dependent on a Player or Block depending on its type, I would have to iterate over the list and downcast each object using instanceof to pass the relevant dependency.
public void executeEvents(){
for(IEvent event : events){
if(event instanceof PlayerEvent){
((PlayerEvent) event).passPlayer(player);
} else {
((BlockEvent) event).passBlock(block);
}
event.trigger();
}
}
I read that downcasting should never be done under any circumstances, so I've been wondering what alternatives I could use that would follow a similar simple execution path but falls under good OOP practice? Or should I just eliminate the interface altogether and have a separate List for each event type?
I read that downcasting should never be done under any circumstances,
so I've been wondering what alternatives
I would not generalize. Applications/libraries that generate code or use reflection generally may use downcast.
In other cases, downcast should indeed be avoided.
You have multiple ways to achieve your goals without downcasting.
1) Don't manipulate a too broad type in the List. Additionally you could make IEvent a generic interface and generalize passPlayer() and passBlock() in pass() that you will move up in the interface.
The interface could look like :
public interface IEvent<T> {
void trigger();
void pass(T t);
}
And implementation of it could look like :
public class PlayerEvent implements IEvent<Player> {
private Player player;
public void trigger() {
// player does things
}
#Override
public void pass(Player t) {
}
}
Now with a more specific typed List you could write :
private Player player = ...;
public void executeEvents() {
List<IEvent<Player>> events = ...;
for (IEvent<Player> event : events) {
event.pass(player);
}
}
2) Use the visitor pattern to benefit from a double dispatch.
Event -> Visitor -> processing.
Each pass() method become a method of the Visitor.
You could enrich the IEvent interface to add an accept() method that accepts a Visitor :
public interface IEvent {
void trigger();
void accept(Visitor visitor);
}
Here the Visitor interface and implementation :
Visitor interface
public interface Visitor {
void visitBlockEvent(BlockEvent block);
void visitPlayerEvent(PlayerEvent player);
}
Visitor implementation
public class ProcessEventVisitor implements Visitor {
private Player player;
private Block block;
#Override
public void visitBlockEvent(BlockEvent blockEvent) {
// do your processing
}
#Override
public void visitPlayerEvent(PlayerEvent playerEvent) {
// do your processing
}
}
IEvent subclasses delegate now to the Visitor parameter the processing :
public class PlayerEvent implements IEvent{
public void trigger() {
// player does things
}
#Override
public void accept(Visitor visitor) {
visitor.visitPlayerEvent(this);
}
}
And the client code can now look like :
private Player player;
public void executeEvents() {
List<IEvent> events = ...;
ProcessEventVisitor visitor = new ProcessEventVisitor();
for (IEvent event : events) {
event.accept(visitor);
}
}
I am writing a library in Java, which throws an event of different types with differing data depending on the type.
For example, here is the extended EventObject:
public class FooEvent extends EventObject {
private final int eventType;
private final Object fooEventObject;
public FooEvent(int type, Object obj){/*...*/}
public int getEventType() {/*...*/}
public int getEventObject() {/*...*/}
}
And here is how I my listener currently looks like:
FooEventListener listener = new FooEventListener() {
#Override
public void onDataChange(FooEvent event) {
switch(event.getEventType()) {
case EVENT_TYPE_BAR:
Bars bar = (Bars)event.getEventObject();
/*work with Bar object...*/
break;
case EVENT_TYPE_GOO:
Goo goo = (Goo)event.getEventObject();
/*work with Goo object...*/
break;
/* etc ...*/
}
}
}
I would like to know if this is the right way of solving this problem (although I doubt it is, since the user of the library would need to know what type to cast to) wherein I have different event types with objects and I do not want to go and make a different event & listener for each one.
Guava's EventBus provides a slightly different approach that can handle multiple event types.
There is unfortunately no easy solution to have a type safe event system with different types. You either have to have 1 listener / publishing implementation per type of you need to teach one side about all the event types that exist.
There is a way to remove the need for instanceof or switch (type) and casting though: the Visitor Pattern
The pattern uses the fact that event objects know their own type which means they can call the right method. The downside is that you need a listener interface that contains all the types.
public class Test {
abstract static class EventObject {
protected abstract void deliver(EventListener listener);
}
static class AEvent extends EventObject {
#Override
protected void deliver(EventListener listener) {
listener.onAEvent(this);
}
}
static class BEvent extends EventObject {
#Override
protected void deliver(EventListener listener) {
listener.onBEvent(this);
}
}
interface EventListener {
void onAEvent(AEvent event);
void onBEvent(BEvent event);
// ...
}
private static final EventListener LISTENER = new EventListener() {
#Override
public void onBEvent(BEvent event) {
System.out.println("Got B Event! " + event);
}
#Override
public void onAEvent(AEvent event) {
System.out.println("Got A Event! " + event);
}
};
private static void notifyListeners(EventObject event) {
event.deliver(LISTENER);
}
public static void main(String[] args) {
notifyListeners(new AEvent());
notifyListeners(new BEvent());
}
}
A better way to solve this is with generics.
public class FooEvent<T> extends EventObject {
private final T fooEventObject;
public FooEvent(T obj){/*...*/}
public T getEventObject() {/*...*/}
}
//usage
SomeType object = new SomeType();
new FooEvent<SomeType>(object);
I think it's a way to go, but not the cleanest way. You should create an abstract class
public abstract class AbstractEventType<T> extends EventObject {}
and extend from that:
public abstract class FooEvent extends AbstractEventType<Foo> {}
public abstract class BarEvent extends AbstractEventType<Bar> {}
Then you need to fire different events and also have different event listeners based on the type:
public interface FooEventListener {
public void onFooChange(FooEvent fooEvent);
}
etc.
If you want to stick with only one event type then you could at least move the code to determine the type to your framework and avoid pollution of the "business" code, by creating one handler method per type, e.g.
public interface MyEventListener {
public void onFooChange(EventType<Foo> eventType);
public void onBarChange(EventType<Bar> eventType);
}
I have the following (maybe common) problem and it absolutely puzzles me at the moment:
There are a couple of generated event objects which extends the abstract class Event and I want to divide them to Session Beans, like
public void divideEvent(Event event) {
if (event instanceof DocumentEvent) {
documentGenerator.gerenateDocument(event);
} else if (event instanceof MailEvent) {
deliveryManager.deliverMail(event);
...
}
...
}
But there could be more than two event types in future, so the if-else will be long and maybe unreadable. Additionally I think instanceof is not really "best practice" in this case.
I could add an abstract method to the Event type and have them divide itself but then I have to inject the specific Session Beans within each entity.
Is there any hint to achieve a "pretty" solution for this problem?
Thanks for any help!
The simplest approach is to have the Event provide a method you can call so the Event knows what to do.
interface Event {
public void onEvent(Context context);
}
class DocumentEvent implements Event {
public void onEvent(Context context) {
context.getDocumentGenerator().gerenateDocument(this);
}
}
class MailEvent implements Event {
public void onEvent(Context context) {
context.getDeliveryManager().deliverMail(event);
}
}
class Context {
public void divideEvent(Event event) {
event.onEvent(this);
}
}
Polymorphism is your friend.
class DocumentGenerator {
public void generate(DocumentEvent ev){}
public void generate(MainEvent ev){}
//... and so on
}
Then just
DocumentGenerator dg = new DocumentGenerator();
// ....
dg.generate(event);
Update
A number of people have raised the objection that you "have to know the kinds of event at compile time." And, yes, you clearly have to know what events you're interpreting at compile time of the generator part, when else would you be able to write the generating part?
These competing examples use Command pattern, which is fine, but means Events have to know the details not just of their representation but of how to print their representation. That means each class may have two kinds of requirements changes to which their sensitive: changes in what events represent, and changes in the way the events are represented in print.
Now, consider, for example, needing to internationalize this. In the Command-pattern case, you have to go to n classes for n different Event types and write new do methods. In the polymorphism case, the changes are localized to one class.
Naturally if you need to internationalize once, you may need many languages, which drive you to adding something like a Strategy to each class in the Command-pattern case, requiring now n classes × m languages; again, you need only have one strategy and one class in the polymorphism case.
There are reasons to choose either approach, but to claim the polymorphism approach is wrong is just incorrect.
Each event has a function, say do.
Each subclass overrides do, to do (:P) the appropriate action.
Dynamic dispatch does everything else afterwards.
All you need to do, is call event.do()
I have no commenting rights and i dont know the exact answer. But is it just me or some ppl here suggest using overloading (which happens at compile time and therefore just generate compile error) to solve this problem?
Just an example. As you see, it will not compile.
package com.stackoverflow;
public class Test {
static abstract class Event {}
static class MailEvent extends Event {}
static class DocEvent extends Event {}
static class Dispatcher {
void dispatchEvent(DocEvent e) {
System.out.println("A");
}
void dispatchEvent(MailEvent e) {
System.out.println("B");
}
}
public static void main(String[] args) {
Dispatcher d = new Dispatcher();
Event e = new DocEvent();
d.dispatchEvent(e);
}
What's the problem with exploiting the method resolution order?
public void dispatchEvent(DocumentEvent e) {
documentGenerator.gerenateDocument(event);
}
public void dispatchEvent(MailEvent e) {
deliveryManager.deliverMail(event);
}
Let Java do the work of matching the correct argument type, then just dispatch the event properly.
This is a typical use case for Sum types, also known as tagged unions. Unfortunately, Java does not support them directly, so they have to be implemented using some variation of the visitor pattern.
interface DocumentEvent {
// stuff specific to document event
}
interface MailEvent {
// stuff specific to mail event
}
interface EventVisitor {
void visitDocumentEvent(DocumentEvent event);
void visitMailEvent(MailEvent event);
}
class EventDivider implements EventVisitor {
#Override
void visitDocumentEvent(DocumentEvent event) {
documentGenerator.gerenateDocument(event);
}
#Override
void visitMailEvent(MailEvent event) {
deliveryManager.deliverMail(event);
}
}
Here we have defined our EventDivider, now to provide a dispatch mechanism:
interface Event {
void accept(EventVisitor visitor);
}
class DocumentEventImpl implements Event {
#Override
void accept(EventVisitor visitor) {
visitor.visitDocumentEvent(new DocumentEvent(){
// concrete document event stuff
});
}
}
class MailEventImpl implements Event { ... }
public void divideEvent(Event event) {
event.accept(new EventDivider());
}
Here I used maximum possible separation of concerns so that responsibility of each class and interface is one and only one. In real life projects DocumentEventImpl, DocumentEvent implementation and DocumentEvent interface declaration are usually merged into a single class DocumentEvent, but that introduces circular dependencies and forces some dependencies between concrete classes (and as we know, one should prefer to depend on interfaces).
Additionally, void should usually be replaced with a type parameter to represent the result type, like this:
interface EventVisitor<R> {
R visitDocumentEvent(DocumentEvent event);
...
}
interface Event {
<R> R accept(EventVisitor<R> visitor);
}
This allows one to use stateless visitors, which are very nice to deal with.
This technique allows to (almost?) always eliminate instanceof mechanically rather than having to figure out a problem-specific solution.
You could register each of your handler classes against each event type, and perform dispatch when event happens like this.
class EventRegister {
private Map<Event, List<EventListener>> listerMap;
public void addListener(Event event, EventListener listener) {
// ... add it to the map (that is, for that event, get the list and add this listener to it
}
public void dispatch(Event event) {
List<EventListener> listeners = map.get(event);
if (listeners == null || listeners.size() == 0) return;
for (EventListener l : listeners) {
l.onEvent(event); // better to put in a try-catch
}
}
}
interface EventListener {
void onEvent(Event e);
}
And then get your specific handlers to implement the interface, and register those handlers with the EventRegister.
You could have a Dispatcher interface, defined like
interface Dispatcher {
void doDispatch(Event e);
}
with implementations like DocEventDispatcher, MailEventDispatcher, etc.
Then define a Map<Class<? extends Event>, Dispatcher>, with entries like (DocEvent, new DocEventDispatcher()). Then your dispatch method could be reduced to:
public void divideEvent(Event event) {
dispatcherMap.get(event.getClass()).doDispatch(event);
}
Here's a unit test:
public class EventDispatcher {
interface Dispatcher<T extends Event> {
void doDispatch(T e);
}
static class DocEventDispatcher implements Dispatcher<DocEvent> {
#Override
public void doDispatch(DocEvent e) {
}
}
static class MailEventDispatcher implements Dispatcher<MailEvent> {
#Override
public void doDispatch(MailEvent e) {
}
}
interface Event {
}
static class DocEvent implements Event {
}
static class MailEvent implements Event {
}
#Test
public void testDispatcherMap() {
Map<Class<? extends Event>, Dispatcher<? extends Event>> map = new HashMap<Class<? extends Event>, Dispatcher<? extends Event>>();
map.put(DocEvent.class, new DocEventDispatcher());
map.put(MailEvent.class, new MailEventDispatcher());
assertNotNull(map.get(new MailEvent().getClass()));
}
}
Not sure how to title this...
So I've got three child classes of Event: WeightEvent, TimedEvent, RepEvent. Through whatever means, I get an object of one of the children. Now I want to send that child event to a method in another object so it can pull the data from it with the getSavedEvents() method. The method only exists in the children since pulling the data is specific to the type of event.
I started with
public void setEvent(Event e) {
but that cast my child object to an Event (parent) object.
Is there any way around this short of writing three different methods. One each for the children?
public void setEvent(WeightEvent e) {
public void setEvent(TimedEvent e) {
public void setEvent(RepEvent e) {
Thanks for any advice.
-John
Even though the reference is cast, it doesn't change the type of the actual object. When you pass the reference on, it will still be a reference to an instance of the child object. Normally this would be enough, with appropriate abstract methods in the parent type if necessary.
However, if the methods you want are specific to the types of the children and you can't come up with an appropriate abstraction which all of them can implement generically, then either you've got to use instanceof within your setEvent code or you do have to overload your method... because you're going to have to call different bits of code depending on the exact type of the event.
This is all a bit vague because we can't see any of your code except a couple of method signatures. If you could give us more details about what you're trying to do, particularly in terms of what setEvent needs to achieve and what the different methods in the child classes are, we may be able to help more.
Instead of switching on the type you should call a method on the event that's defined differently for each type of event type. This is called the Template method pattern. (It has nothing to do with C++ templates, BTW)
Using this pattern, your EventTable class becomes something like this:
public class EventTable {
public void setEvent(Event e) {
int x = 0;
columns = e.getFields();
Event[] savedEvents = e.getSavedEvents();
for(Event ev : savedEvents) {
tempdata[x] = ev.getTempData();
x++;
}
}
}
Note that the entire switch has been replaced with a single call to getTempData(). This method is then abstract in Event, just like getSavedEvents:
public abstract class Event {
public Date getDate() { return(_date); }
public abstract Event[] getSavedEvents();
public abstract int[] getTempData();
public int[] getFormattedDate() {
...
}
Then you define the getTempData() method in each subclass. For example:
public class WeightEvent extends Event {
public int getWeight() { return(_weight); }
public int getReps() { return(_reps); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getWeight(),
getReps()
};
}
}
public class TimedEvent extends Event {
public String getTimeInHMS() { return(_timeString); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getTimeInHMS()
};
}
}
public class RepEvent extends Event {
public int getReps() { return(_reps); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getReps()
};
}
}
You could use generics to do this.
Define the Event class as follows:
public abstract class Event<T extends Event> {
public abstract void setEvent(T e);
}
This defines a class that expects to be created with any type that extends Event.
Then in your child classes you implement something like this using the child class as the generic type:
class WeightEvent extends Event<WeightEvent>
{
#Override
public void setEvent(WeightEvent e) {
...
}
}
I think your probem is calling getSavedEvents() when having an Event variable.
If so, add an abstract getSavedEvents() method to Event, which must also be declared abstract :
public abstract class Event {
public abstract Events getSavedEvents();
...
}
since Eventis abstract you can not create an instance of it; it must be subclassed to be used. If that is a problem, throw an Exception or do anything reasonable for your application (nothing at all, just return null) in Event.getSavedEvents():
public class Event {
public Events getSavedEvents() {
throw new UnsupportedOperationException("must be called in a child class");
// OR return null;
...
}
now you can call the getSavedEvents() method in your other object:
public class OtherObject {
private Event event;
public void setEvent(Event e) {
event = e;
...
Events events = event.getSavesEvents();
the method implemented by the real class of e will be used, e.g. if e is a TimedEvent, the method in that class will be called.
You could abstract the problem out behind an interface
interface IEvent
{
abstract public void doSomething();
}
Then have all your event classes implement it, e.g.
class WeightedEvent implements IEvent
{
public void doSomething()
{
// do something
}
}
Then you only need a single method and don't need to do any type checking
public void setEvent(IEvent e)
{
e.doSomething();
}
HTH
May be you can use a Visitor pattern.
Using abstract helped with the getSavedEvents() method, since all of the children implement that method.
Here's the code for setEvent():
public class EventTable {
public void setEvent(Event e) {
int x = 0;
int type = e.getEventType();
columns = e.getFields();
Event[] savedEvents = e.getSavedEvents();
for(Event ev : savedEvents) {
tempdata[x][0] = ev.getFormattedDate()[0];
switch(type) {
case EVENTTYPE.WEIGHT:
tempdata[x][1] = ev.getWeight();
tempdata[x][2] = ev.getReps();
break;
case EVENTTYPE.TIMED:
tempdata[x][1] = ev.getTimeInHMS();
break;
case EVENTTYPE.REP:
tempdata[x][1] = ev.getReps();
break;
}
x++;
}
}
}
This code works after I added "abstract" to the Event class and defined an abstract method called getSavedEvents().
The next problem is the getWeight(), getReps() and getTimeInHMS() methods. They are specific to the type of child event and again don't exist in the parent Event class. If I make them abstract in Event, now I have to define them in each child, even though getReps() has no context for a TimedEvent.
public class Event {
public Date getDate() { return(_date); }
}
public class WeightEvent extends Event {
public int getWeight() { return(_weight); }
public int getReps() { return(_reps); }
}
public class TimedEvent extends Event {
public String getTimeInHMS() { return(_timeString); }
}
public class RepEvent extends Event {
public int getReps() { return(_reps); }
}
Abbreviated code, obviously. WeightEvents have a date, weight and reps associated with them. TimedEvents have a date and length of time associated with them. RepEvents have a date and number of reps associated to them. The date methods are all in the parent since they are common across events.
If I don't make getWeight(), getReps() abstract and only declare them in the child where they are relevant, here's the error I get from EventTable in the above copied setEvent() method:
EventTable.java:124: cannot find symbol
symbol : method getWeight()
location: class Event
tempdata[x][1] = ev.getWeight();
-John
You could cast the Event e object to the child classes -- I think the instanceof operator in Java will help you.