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.