Appropriate use of Event-Listener pattern - java

I appreciate this may not be a right/wrong type question, possibly more a stylistic thing but I often find myself pondering the use (overuse?) of custom Event and EventListener classes.
Frequently I have a class (often a GUI component) that needs to make other components aware of some change in it's state.
I could maintain a list of ChangeListeners (or some other already defined, general purpose listener type) and then call them on a state change, for example:
for (final ChangeListener cl : changeListeners)
cl.stateChanged(new ChangeEvent(this));
then retrieve the value in the listener:
class SomeListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
((MyClass) e.getSource()).getSomeStateProperty();
.
.
.
}
However the cast to MyClass strikes me as bad practice as the listener class is now making an explicit assumption about the contents of that ChangeEvent which has not been explicitly declared as the ChangeEvent constructor takes type Object.
So I frequently find myself creating pairs of custom Event and EventListener classes/interfaces i.e.
public interface SomeThingChangeListener extends EventListener {
/**
* Invoked when the target of the listener has changed some thing.
*
* #param e a SomeThingChangeEvent object
*/
void someThingChanged (SomeThingChangeEvent e);
}
With a corresponding Event class that contains a reference to the pertinent change information (probably a reference to an interface or abstract class in the event constructor).
The thing that bothers me about this however is the large proliferation of these small connector classes/interfaces for all 'things' that might 'happen' that may only ever have one concrete implementation.
So I guess the question is; is it best just to use general purpose events/listeners wherever you can or to always make class/event specific events and listeners?
The main reason that I seem to create quite a lot of these is that it often occurs to me that the association between two (or more) classes tends to be fairly weak, they are often not really related to each other in any way but one may be interested in information/state created/modified by another but not care about the details of the source. I find the observer or event/listener pattern a good way to keep coupling between unrelated classes to a minimum.
Any thoughts?
Thanks in advance,
Simon.

In my opinion defining specific types for each event, which makes up your domain model, is a good practice (one I do prefer / follow most of the times). Having as many event listeners as different event types may cause class pollution. On the other side, a generic listener approach leads to either determine the event type by sequences of instanceof or using the Visitor Pattern to dispatch events. The Visitor Pattern couples events to the listener. Perhaps a compromise between listeners capable of consuming more than one event (having change listener methods for related events) will reduce the number of different listeners by preserving event specific consuming, avoiding sequences of instanceof.
A proper solution depends on the concrete project and is always a tradeoff of many aspects.

Related

What exactly is the difference between an app specific event and a GWT event and when is one supposed to be used over the other?

While consulting the javadocs for GwtEvent class this text snippet got me confused:
There is no need for an application's custom event types to extend
GwtEvent. Prefer Event instead.
Can someone please give a concrete situation example where Event is preferred to the gwtevent class?
Should ClearEvent ( defined here : http://alextretyakov.blogspot.ro/2011/11/gwt-event-bus-basics.html ) extend GwtEvent class or should it directly extend Event class?
GwtEvent extends Event. It just seems that the GWT team need some functionalities for most of its events. But you probably don't need those.
In our application most events are consumed directly. So we don't need to have those isLive(), kill(), revive() methods. I guess it's the same for most people.
IMO such methods are required when a chain of listeners can catch the event and forward it to each other. You would want to mark the event as "processed" to avoid it being consumed when the processing is over.
The code in the post you provided is not using those methods. So the answer is: the author didn't need to extends GWTEvent. Event will work just fine.

Best practice - Declaring an event as part of a Java interface

I'm attempting to decouple some UI code using interfaces and events, and I would like to know if there is way/best practice in Java for declaring an event as part of a Java interface - something like what C# provides:
// C# event declaration in interface
public interface IAction
{
event EventHandler OnAction;
}
My goal is simply to mark an interface so that it is known it (implementors) fires events of a particular type. I'm hoping I can include more than documentation only to enforce that behaviour. I realize Java does not provide the "event" keyword or a direct way of doing this, so I'm hoping for some advice on a workaround or best practice on achieving this.
One way I can think of doing this is by creating a generic marker interface that represents the capability to fire events:
public interface FiresEvent<T extends Event> {
public void fireEvent();
}
... and then to inherit that interface in my custom interface.
public interface MyInterface extends FiresEvent<ActionEvent> {
}
The problem with this approach is that "FiresEvent" can only be inherited once, even if the generic type changes, so the solution does not seem generic enough for the case where an object may be the source of multiple events.
I'd be curious to know how people would handle this, and if there is a better way than to just document the need to fire events.
EDIT:
Maybe the following will clear up my question:
I understand the Java handler list approach and self-handling by allowing callers to register handlers against an object. In my case I am relying on an event bus, so we can view "firing" events as putting them out there, for something else to redirect to handlers.
I'd like to define the interface responsibility as:
The interface implementer fires an event of type T into the world/event bus/anything
The interface implementer does not have to delegate to registered listeners itself
Java handles events a bit differently than what you're used to, however the concept is the same. You create what's called an event listener, and it's called when the event happens. This can be a better construct as it allows for multiple listeners to be registered.
I suggest browsing this tutorial
The presence of a method
registerXListener(XListener listener)
in the interface indicates that a class will send out XEvents to those that care. That is, the 'marker' is just another method. The nearest analog of the C# idiom (I think) would be to lift that method into an interface, like
public interface XEventFirer
{
public void registerXListener(XListener listener)
}
This seems like a natural place to use annotations. I have come across EventBus which uses annotations to for publishing and subscribing to events. This approach is naturally self-documenting and depending on how it's implemented could make your code more readable and maybe allow you to enforce the annotation.

Is this a good way to handle events in Java?

I'm making a game in Java, and I think I have a good idea of how to handle events. Does this sound right?
A Window class--the view. It's a representation of the World at the current moment.
There's also a Game class -- the controller. (The model's implementation is irrelevant for this question).
The Window class doesn't care about events. Therefore, the event listener simply dispatches them to the Game class (via something like game.notifyEvent(Event e);.
The Game class, upon receipt of this event, will start updating values and the like, and some variables (like the location of the player) will be changed. At this point, it uses its class variable Window w to notify it of the changes (via various methods such as w.movePlayer(Position p), etc.
SO, does this sound like something that would make sense to you?
Yes, what you're doing makes some sense. I find it much more intuitive to have the Window listen to the Game than the other way round. I've also found that Java is much more maintainable if you separate out the different areas of the GUI and pass the Game into each of them through a fine-grained interface. I normally get the GUI elements to listen to changes in the model, and request any interactions to be dealt with. This way round makes for easier unit testing, and you can replace the GUI with a fake for acceptance testing if you don't have a decent automation suite, or even just for logging.
Usually splitting up the GUI results in some panels purely listening, and some panels purely interacting. It makes for a really lovely separation of concerns. I represent the panels with their own classes extending JPanel, and let the Window pass the Game to them on construction.
So for instance, if I have two panels, one of which displays the results and one of which has an "Update" button, I can define two interfaces: INotifyListenersOfResults and IPerformUpdates. (Please note that I'm making role-based interfaces here using the IDoThisForYou pattern; you can call them whatever you like).
The Game controller then implements both these interfaces, and the two panels each take the respective interface. The Update interface will have a method called RequestUpdate and the Results interface will have AddResultsListener. Both these methods then appear on the Game class.
Regardless of whether you get the Game to listen to the Window or the Window to the Game, by separating things through interfaces this way you make it much easier to split the Game controller later on and delegate its responsibilities, once things start getting really complicated, which they always do!
I think you should implement the Observer design pattern (http://en.wikipedia.org/wiki/Observer_pattern) without using .NET's events. In my approach, you need to define a couple of interfaces and add a little bit of code. For each different kind of event, create a pair of symmetric interfaces
public interface IEventXDispatcher
{
void Register(IEventXHandler handler);
void Unregister(IEventXHandler handler) throws NotSupportedException;
}
public interface IEventXHandler
{
void Handle(Object sender, Object args);
}
X denotes the specific name of event (Click, KeyPress, EndApplication, WhateverYouWant).
Then make your observed class implement IEventDispatcher and your observer class(es) implement IEventHandler
public class Dispatcher implements IEventXDispatcher, IEventYDispatcher ...
{
private List<IEventXHandler> _XHandlers;
private List<IEventYHandler> _YHandlers;
void Register(IEventXHandler handler)
{
_XHandlers.Add(handler);
}
void Unregister(IEventHandler handler) throws NotSupportedException
{
//Simplified code
_XHandlers.Remove(handler);
}
private MyMethod()
{
[...]
for(IEventXHandler handler: _XHandlers)
handler.Handle(this, new AnyNeededClass())
[...]
}
//Same for event Y
All the code is hand-written. I have little experience with Java but I believe this pattern may help you!

Is there a better way than a sequence of if's to handle events?

I recently ran across several objects implemented to handle events with a hard coded mapping using this pattern:
public void handleEvent(Event event)
{
if(event.getCode() == SOME_STATIC_EVENT)
doSomething(event);
if(event.getCode() == ANOTHER_STATIC_EVENT)
doSomethingElse(event);
}
where doSomething functions are implemented as methods of the same class.
In hopes of striving for looser coupling, how would you suggest abstracting out this pattern? Also, what's the best approach for mapping 0..N functions to a fired event?
Yes, basically what you want to do is create a data structure that maps an event type to an interface. Here's a simple one implemented as a map.
EventHandlerInterface h;
// eventMap contains a mapping of event codes to
// implementations of EventHandlerInterface
h = eventMap.get(event.getCode());
if(h != null)
{
h.handle(event);
}
This gives you the ability to efficiently handle a large number of events and dynamically add, remove, and remap events to different handlers.
There was recently a SOF post that was similar and close enough that my response here can answer your question quite well.
Rather than a runnable, you would make your own interface:
public abstract interface EventHandler
{
public void run(Event event);
}
You can start by making the code a little cleaner. Use a local variable to take out the repeated event.getCode(). Switch to enums so you can use switch.
If there is a repeated pattern you can decode to a multiple method callback interface, like AWT does.
I would suggest that the registration of the even becomes more specific. Register a different callback for each event type. Even as far as taking the event code out of the event, and perhaps removing the event. Under the sheets you might keep the event code for a mapping to handlers, but this should be opaque. The downside to this approach is that anonymous inner classes are currently (JDK6) highly verbose and class handling is inefficient (load times and perm gen footprint).

Is there an standard class for Events in Java?

I wrote a Listener. Now I want to notify it, when a change occurs. Nothing special.
Now I'm asking myself:
Is there I standard class for Events that I can use, or do I have to write a new one by myself?
I know there ara java.awt.Event and AWTEvent. But I am not working directly at GUI level here. Furthermore we are using Swing at GUI level. So I'm not shure if it is a good idea to mix Swing and AWT.
Thx
Its ancient and simple, but you could use Observer/Obserable in java.util:
java.util
public class Observable extends Object
This class represents an observable
object, or "data" in the model-view
paradigm. It can be subclassed to
represent an object that the
application wants to have observed.
An observable object can have one or
more observers. An observer may be any
object that implements interface
Observer. After an observable instance
changes, an application calling the
Observable's notifyObservers method
causes all of its observers to be
notified of the change by a call to
their update method.
For more info, try http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto.html.
There's nothing special about events in Java. If your events are not GUI events, then it would be less confusing for you to use your own class and not mix them with java.awt.Events.
If you are using swing, you can take a look at EventBus:
The Event Bus is a single-process publish/subscribe event routing library, with Swing extensions. The EventBus is fully-functional, with very good API documentation and test coverage (80+%). It has been deployed in many production environments, including financial, engineering and scientific applications.
I've always used EventObject as the base class for my custom events. Here's what the JavaDoc says:
The root class from which all event state objects shall be derived.
All Events are constructed with a
reference to the object, the "source",
that is logically deemed to be the
object upon which the Event in
question initially occurred upon.
Kind of a standard solution in Swing apps is to maintain a list of event listeners in the class the event originates from. When the event occurs you iterate over the list and notify each listener of the event. So it can be something like this (I omitted the access modifiers and some of the type declarations for brevity):
class SomeClassInWhichTheEventOccurs {
List<MyListener> listeners;
void addListener(listener) { listeners.add(listener); }
void removeListener(listener) { listeners.remove(listener); }
void fireEvent(someEventParameters) {
foreach (listener in listeners) listener.eventOccured();
}
void someMethodInWhichTheEventOccurs() {
...
fireEvent(someEventParameters);
}
}
The event parameters can be just anything: you can create your own event class, reuse java.awt.Event, or pass some parameters of arbitrary types.
Swing is based upon AWT, so you have to mix it. The problem comes with mixing AWT heavyweight components with Swing lightweight components. Don't use AWT heavyweight components.
Just to be notified that something has changed javax.swing.event.ChangeListener is fine. In fact, so long as you are not using a library that assumes the beans model, you can ignore event classes and use a observer without an event object.

Categories

Resources