4

I'm always writing observer/subject interfaces in a particular Java project, e.g.:

/**
 * Registers the receiver to the dispatcher. 
 * When data arrives that the receiver can process, 
 * it will be passed to the receiver.
 * ...
 */
void addReceiver(IDataReceiver receiver);

/**
 * @return
 *      True, if the receiver has been registered, false otherwise.
 * ...
 */
boolean hasReceiver(IDataReceiver receiver);

...

When a class implements these interfaces, I have to implement the code, test it, debug it, etc. It feels so futile to keep reimplementing such similar logic. Is there any better option in Java?

  • 1
    We need a bit more context than this. Can you post some more example code, perhaps one of your implementations? – Robert Harvey Aug 12 '14 at 22:50
  • My problem essentially comes down to implementing callback functions in Java. It feels incredibly clumsy to keep re-writing event handling code. I'm not sure how more code could be of use :S – Dylan Knowles Aug 12 '14 at 22:54
  • It would tell us why you are using the callback functions in the first place, and perhaps suggest to us a better way that does not involve callback functions, or show us why we should tell you that callback functions are the best way (if that is, indeed, the case). – Robert Harvey Aug 12 '14 at 23:01
4

There are some abstractions in the Java API for the Observer Pattern. For example the java.beans.PropertyChangeListener. In combination with the java.beans.PropertyChangeSupport it's possible to abstract your problem a little bit.

This example is from the Oracle Doc of Java:

public class MyBean {
 private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

 public void addPropertyChangeListener(PropertyChangeListener listener) {
     this.pcs.addPropertyChangeListener(listener);
 }

 public void removePropertyChangeListener(PropertyChangeListener listener) {
     this.pcs.removePropertyChangeListener(listener);
 }

 private String value;

 public String getValue() {
     return this.value;
 }

 public void setValue(String newValue) {
     String oldValue = this.value;
     this.value = newValue;
     this.pcs.firePropertyChange("value", oldValue, newValue);
 }

 [...]
}

With the String in firePropertyChange you can define, which property is changed. Of course, because of the use of the String the type safety is lost.

You won't get rid of this part before Java8:

 private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

 public void addPropertyChangeListener(PropertyChangeListener listener) {
     this.pcs.addPropertyChangeListener(listener);
 }

 public void removePropertyChangeListener(PropertyChangeListener listener) {
     this.pcs.removePropertyChangeListener(listener);
 }

The only possibility is, to inherit it from an abstract base class. But if you do that, you can not have another base class.

Since Java8 you can define default methods in interfaces. You can define an interface like that:

public interface Listenable {
    PropertyChangeSupport getPropertyChangeSupport ();

    default void addPropertyChangeListener(PropertyChangeListener listener) {
        getPropertyChangeSupport ().addPropertyChangeListener(listener);
    }

    default void removePropertyChangeListener(PropertyChangeListener listener) {
        getPropertyChangeSupport ().removePropertyChangeListener(listener);
    }
}

The getter is needed, because Interfaces can't have members directly.

Then it should be possible to avoid a little bit more boilerplate code:

public class MyBean implements Listenable {
 private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
 @Override     
 public PropertyChangeSupport getPropertyChangeSupport () {
     return pcs;
 }

 private String value;

 public String getValue() {
     return this.value;
 }

 public void setValue(String newValue) {
     String oldValue = this.value;
     this.value = newValue;
     this.pcs.firePropertyChange("value", oldValue, newValue);
 }

 [...]
}

Well, I don't see a possibility in Java, to do it completely without boilerplate code.

  • I'm excited for Java8, then. Default methods look like mixins that are available in Scala, which effectively remove the need for the boilerplate. In the meantime... boilerplate it is. T_T – Dylan Knowles Aug 13 '14 at 15:44
  • Yes, default methods are some like mixins in Scala. Java8 is released since March 2014, you don't have to wait ;-) – F. Böller Aug 13 '14 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.