Ci sono alcune astrazioni nell'API Java per Observer Pattern
. Ad esempio java.beans.PropertyChangeListener
. In combinazione con java.beans.PropertyChangeSupport
è possibile astrarre un po 'il tuo problema.
Questo esempio è di 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);
}
[...]
}
Con String
in firePropertyChange
puoi definire, quale proprietà è cambiata. Ovviamente, a causa dell'uso di String
, il tipo di sicurezza viene perso.
Non ti libererai di questa parte prima di 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);
}
L'unica possibilità è di ereditarlo da una classe base astratta. Ma se lo fai, non puoi avere un'altra classe base.
Poiché Java8 è possibile definire i metodi predefiniti nelle interfacce. Puoi definire un'interfaccia del genere:
public interface Listenable {
PropertyChangeSupport getPropertyChangeSupport ();
default void addPropertyChangeListener(PropertyChangeListener listener) {
getPropertyChangeSupport ().addPropertyChangeListener(listener);
}
default void removePropertyChangeListener(PropertyChangeListener listener) {
getPropertyChangeSupport ().removePropertyChangeListener(listener);
}
}
È necessario getter
, perché le interfacce non possono avere membri direttamente.
Quindi dovrebbe essere possibile evitare un po 'più codice standard:
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);
}
[...]
}
Bene, non vedo una possibilità in Java, di farlo completamente senza codice boilerplate.