Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java. Correct pattern for implementing listeners

Very typically I have a situation where a given object will need to have many listeners. For instance, I might have

class Elephant {   public void addListener( ElephantListener listener ) { ... } } 

but I'll have many such situations. That is, I'll also have a Tiger object that'll have TigerListeners. Now, TigerListeners and ElephantListeners are quite different:

interface TigerListener {   void listenForGrowl( Growl qrowl );   void listenForMeow( Meow meow ); } 

while

interface ElephantListener {   void listenForStomp( String location, double intensity ); } 

I find that I always have to keep re-implementing the broadcasting mechanism in each animal class, and the implementation is always the same. Is there a preferred pattern?

like image 860
Jake Avatar asked Jun 04 '10 16:06

Jake


People also ask

What is listener method?

Listener methods are the main approach by which you add application-specific behavior to your application. Listener methods are a kind of call back; they are triggered when a form is submitted or a link is clicked. The listener methods exist within your page and component classes.


1 Answers

Instead of each Listener having specific methods for every event type you can send it, change the interface to accept a generic Event class. You can then subclass Event to specific subtypes if you need, or have it contain state such as double intensity.

TigerListener and ElephentListener then become

interface TigerListener {     void listen(Event event); } 

In fact, you can then further refactor this interface into a plain Listener:

interface Listener {     void listen(Event event); } 

Your Listener implementations can then contain the logic that they need for the specific events they care about

class TigerListener implements Listener {     @Overrides     void listen(Event event) {         if (event instanceof GrowlEvent) {             //handle growl...         }         else if (event instance of MeowEvent) {             //handle meow         }         //we don't care about any other types of Events     } }  class ElephentListener {     @Overrides     void listen(Event event) {         if (event instanceof StompEvent) {             StompEvent stomp = (StompEvent) event;             if ("north".equals(stomp.getLocation()) && stomp.getDistance() > 10) {                  ...              }         }     } } 

The key relationship between the subscriber and the publisher is that the publisher can send events to the subscribers, it isn't necessarily that it can send it certain types of events - this type of refactoring pushes that logic from the interface down into the specific implementations.

like image 107
matt b Avatar answered Sep 24 '22 00:09

matt b