小编典典
每个事件是否有特定的侦听器接口。每个事件都可以发出侦听器调用。然后,调度程序的作用是识别目标侦听器并在其上触发事件通知。
例如,通用事件定义可以是:
public interface GameEvent {
public void notify( final L listener);
}
如果您的CollisionListener是:
public interface CollisionListener {
public void spaceshipCollidedWithMeteor( Spaceship spaceship, Meteor meteor );
}
然后,相应的事件可以是:
public final class Collision implements GameEvent {
private final Spaceship ship;
private final Meteor meteor;
public Collision( final Spaceship aShip, final Meteor aMeteor ) {
this.ship = aShip;
this.meteor = aMeteor;
}
public void notify( final CollisionListener listener) {
listener.spaceshipCollidedWithMeteor( ship, meteor );
}
}
您可以想象一个调度程序,它能够像以下情况一样在目标侦听器上传播此事件(Events是调度程序类):
// A unique dispatcher
final static Events events = new Events();
// Somewhere, an observer is interested by collision events
CollisionListener observer = ...
events.listen( Collision.class, observer );
// there is some moving parts
Spaceship aShip = ...
Meteor aMeteor = ...
// Later they collide => a collision event is notified trough the dispatcher
events.notify( new Collision( aShip, aMeteor ) );
在这种情况下,调度程序不需要任何有关事件和侦听器的知识。它仅使用GameEvent接口触发向每个侦听器的单独事件通知。每个事件/侦听器对都选择自己的对话方式(如果需要,它们可以交换许多消息)。
这种调度程序的典型实现应类似于:
public final class Events {
/** mapping of class events to active listeners **/
private final HashMap map = new HashMap( 10 );
/** Add a listener to an event class **/
public void listen( Class extends GameEvent> evtClass, L listener) {
final ArrayList listeners = listenersOf( evtClass );
synchronized( listeners ) {
if ( !listeners.contains( listener ) ) {
listeners.add( listener );
}
}
}
/** Stop sending an event class to a given listener **/
public void mute( Class extends GameEvent> evtClass, L listener) {
final ArrayList listeners = listenersOf( evtClass );
synchronized( listeners ) {
listeners.remove( listener );
}
}
/** Gets listeners for a given event class **/
private ArrayList listenersOf(Class extends GameEvent> evtClass) {
synchronized ( map ) {
@SuppressWarnings("unchecked")
final ArrayList existing = map.get( evtClass );
if (existing != null) {
return existing;
}
final ArrayList emptyList = new ArrayList(5);
map.put(evtClass, emptyList);
return emptyList;
}
}
/** Notify a new event to registered listeners of this event class **/
public void notify( final GameEvent evt) {
@SuppressWarnings("unchecked")
Class> evtClass = (Class>) evt.getClass();
for ( L listener : listenersOf( evtClass ) ) {
evt.notify(listener);
}
}
}
我想它可以满足您的要求:
很轻,
快速,
没有强制转换(使用时),
在编译时检查所有内容(没有可能的错误),
侦听器没有API约束(每个事件选择它自己的消息),
进化(不同事件和/或侦听器之间没有依赖关系),
调度员是一个通用的黑匣子,
消费者和生产者不需要彼此了解。
2020-12-03