MVC: PropertyChangeListener vs Java Observer & Observable

Markey

Mitglied
Hallo zusammen,

ich beschäftige mich zur Zeit mit einer MVC-Java-Implementierung mit Observer-Pattern.
Nun ist bei mir die Frage gekommen, welcher Aufbau mehr Sinn macht.

Möglichkeit 1
Ich erbe in meinen Model-Klassen von Observerable und implementiere das Interface Observer in der View. Und nutze die Standard Methoden ala addObserver(Observer o) um die View am Model als Beobachter einzutragen und notifyObservers() um die View über Änderungen am Modell zu informieren.​

Möglichkeit 2
Ich deklariere und initialisiere ein Feld vom Typ PropertyChangeSupport im Model und implementiere das interface PropertyChangeListener in der View. Änderungen am Model werden ja dann über die Methode firePropertyChange(PropertyChangeEvent evt) an die eingetragenen Listener propagiert werden, oder sehe ich das falsch!?​

Welche konkreten Vor- oder Nachteile sehr ihr für die unterschiedlichen Implementierungen?

Danke für Ihre zahlreichen Antworten,

Mark
 
Hallo zusammen,

ich beschäftige mich zur Zeit mit einer MVC-Java-Implementierung mit Observer-Pattern.
Nun ist bei mir die Frage gekommen, welcher Aufbau mehr Sinn macht.

Möglichkeit 1
Ich erbe in meinen Model-Klassen von Observerable und implementiere das Interface Observer in der View. Und nutze die Standard Methoden ala addObserver(Observer o) um die View am Model als Beobachter einzutragen und notifyObservers() um die View über Änderungen am Modell zu informieren.​

Möglichkeit 2
Ich deklariere und initialisiere ein Feld vom Typ PropertyChangeSupport im Model und implementiere das interface PropertyChangeListener in der View. Änderungen am Model werden ja dann über die Methode firePropertyChange(PropertyChangeEvent evt) an die eingetragenen Listener propagiert werden, oder sehe ich das falsch!?​

Welche konkreten Vor- oder Nachteile seht ihr für die unterschiedlichen Implementierungen?

Danke für Eure zahlreichen Antworten,

Mark

Ich nehme mir mal raus euch zu dutzen 🙂
 
Ich kenne MVC, ich kenne auch sämtliche Forenbeiträge zu dem Thema. :rtfm:Mich interessiert aber nicht was MVC eigentlich ist (zumeist der Fokus der Einträge), sondern was die "Best-Practices" in der Java-Umsetzung sind. Und was andere Entwickler aus welchen Gründen bevorzugen. ???:L

Steht doch einiges in dem Beitrag dazu drin, vor allem zu PropertyChangeSupport
 
Im "klassischen" MVC nimmt man das Observerpattern. D.h. der View beobachtet Models, die entsprechende Aenderungen feuern. Ob dazu das Pattern direkt und an jedem Model implementiert wird (Moeglichkeit 1) oder man irgendwie versucht, den Code zum Pattern auszulagern (Moeglichkeit 2) spielt prinzipiell keine Rolle. Nimm was dir besser gefaellt.

Ich wuerde wahrscheinlich (haengt halt stark vom Umfang usw ab) Weg 1 gehen, da imho Java ziemlich ungeeignet ist, um bestimmte Pattern ansich in eigne Klassen auszulagern.

Allerdings rate ich vom Observerpattern generell ab (bei der Umsetzung von MVC). Irgendwann hat man dann naemlich hunderte von Observern und Observables, die alle irgendwie miteinander verbunden sind. Man verliert einfach den Ueberblick, wenns ein groesseres Projekt wird.

Viel besser gefaellt mit Publish/Subscribe mit einem EventBus. Prinzipiell ist das aehnlich, das was bei Observer der PropertyChangeSupport ist, ist dann eine Instanz von EventBus (die z.B. per DI dem Model und den Views bekannt gemacht wird). Die Models "publishen" ihre Aenderungen auf den Bus, die Views "subscriben" sich dann fuer Aenderungen, die sie interessieren. Code sieht dann z.B. so aehnlich aus (Skizze):
Java:
public class Model {
   public void setFoo( String foo ) {
      eventBus.publish( this, new ModelChanged( this.foo, foo ) );
      this.foo = foo;
   }
}
public class View {
   public void init(Model model) {
      eventBus.subscribe( model, ModelChanged.class, new EventHandler<ModelChanged>() {
          public void handle( ModelChanged event ) {
             updateGUI();
          }
      }
   }
}
public class Controller {
   public void init() {
      eventBus.subscribe( Model.class, ModelLoaded.class, new EventHandler<ModelLoaded>() {
         public void handle( ModelLoaded event ) {
            model = event.getModel();
            view  = viewFactory.getViewFor( model );
            view.init( model );
            showDialog( view );
         }
      }
   }
}

Das Ganze hat mehrere Vorteile, u.a. eine deutlich staerkere Unabhaengigkeit zwischen Model und Views, man kann den EventBus fuer alle moeglichen Events (nicht nur fuer PropertyChanges) verwenden und - das gefaellt mir persoenlich am besten - man kann mehrere EventBusse verwenden, die die handle-Methoden der EventHandler in unterschiedlichen Threads ausfuehren (BackgroundThread, EDT, ...). Zusaetzlich koennte man einen Bus einfuehren, der die Events serialisiert uebers Netzwerk streamt.

Aber es gibt unglaublich viele Moeglichkeiten und MVC beschreibt die Details nicht. MVC sagt eigentlich nur, dass Model und View getrennt wird und es noch einen Controller gibt, der alles zusammenbindet. Wie du das erreichst, haengt einfach total vom konkreten Fall ab.

edit: typo
 
Zuletzt bearbeitet:
Im "klassischen" MVC nimmt man das Observerpattern. D.h. der View beobachtet Models, die entsprechende Aenderungen feuern. Ob dazu das Pattern direkt und an jedem Model implementiert wird (Moeglichkeit 1) oder man irgendwie versucht, den Code zum Pattern auszulagern (Moeglichkeit 2) spielt prinzipiell keine Rolle. Nimm was dir besser gefaellt.

Ich wuerde wahrscheinlich (haengt halt stark vom Umfang usw ab) Weg 1 gehen, da imho Java ziemlich ungeeignet ist, um bestimmte Pattern ansich in eigne Klassen auszulagern.

Allerdings rate ich vom Observerpattern generell ab (bei der Umsetzung von MVC). Irgendwann hat man dann naemlich hunderte von Observern und Observables, die alle irgendwie miteinander verbunden sind. Man verliert einfach den Ueberblick, wenns ein groesseres Projekt wird.

Viel besser gefaellt mit Publish/Subscribe mit einem EventBus. Prinzipiell ist das aehnlich, das was bei Observer der PropertyChangeSupport ist, ist dann eine Instanz von EventBus (die z.B. per DI dem Model und den Views bekannt gemacht wird). Die Models "publishen" ihre Aenderungen auf den Bus, die Views "subscriben" sich dann fuer Aenderungen, die sie interessieren. Code sieht dann z.B. so aehnlich aus (Skizze):
Java:
public class Model {
   public void setFoo( String foo ) {
      eventBus.publish( this, new ModelChanged( this.foo, foo ) );
      this.foo = foo;
   }
}
public class View {
   public void init(Model model) {
      eventBus.subscribe( model, ModelChanged.class, new EventHandler<ModelChanged>() {
          public void handle( ModelChanged event ) {
             updateGUI();
          }
      }
   }
}
public class Controller {
   public void init() {
      eventBus.subscribe( Model.class, ModelLoaded.class, new EventHandler<ModelLoaded>() {
         public void handle( ModelLoaded event ) {
            model = event.getModel();
            view  = viewFactory.getViewFor( model );
            view.init( model );
            showDialog( view );
         }
      }
   }
}

Das Ganze hat mehrere Vorteile, u.a. eine deutlich staerkere Unabhaengigkeit zwischen Model und Views, man kann den EventBus fuer alle moeglichen Events (nicht fuer PropertyChanges) verwenden und - das gefaellt mir persoenlich am besten - man kann mehrere EventBusse verwenden, die die handle-Methoden der EventHandler in unterschiedlichen Threads ausfuehren (BackgroundThread, EDT, ...). Zusaetzlich koennte man einen Bus einfuehren, der die Events serialisiert uebers Netzwerk streamt.

Aber es gibt unglaublich viele Moeglichkeiten und MVC beschreibt die Details nicht. MVC sagt eigentlich nur, dass Model und View getrennt wird und es noch einen Controller gibt, der alles zusammenbindet. Wie du das erreichst, haengt einfach total vom konkreten Fall ab.

Gefällt mir! :applaus:
 
Ich finde das man diese Art Code am besten überhaupt nicht mehr selbst schreibt. Das können Maschinen besser, die machen bei wiederkehrenden Aufgaben keine Fehler.
Deshalb lieber ein EMF Modell verwenden. Das spart dir Arbeit und du musst dir auch nicht mehr überlegen wie man denn nun am besten Property Change Support oder Observer implementiert.
Eclipse Modeling Framework ? Wikipedia
 
[...]Deshalb lieber ein EMF Modell verwenden. Das spart dir Arbeit und du musst dir auch nicht mehr überlegen wie man denn nun am besten Property Change Support oder Observer implementiert.

Dafuer machst du dich von Eclipse abhaengig und bekommst Probleme, sobald du an die Grenzen vom generierten Code gelangst. Zudem verliert man Refactoring Moeglichkeiten.

Grad als Einsteiger finde ich, sollte man erstmal mit den Grundlagen beginnen und eben mal ein Beispielprojekt manuell durchprogrammiert haben. Da bemerkt man schon, was man immer und immer wieder schreiben muss und sucht dann nach Alternativen. Ob man dann EMF nimmt, muss jeder selbst entscheiden.
 
Ich finde das man diese Art Code am besten überhaupt nicht mehr selbst schreibt. Das können Maschinen besser, die machen bei wiederkehrenden Aufgaben keine Fehler.
Deshalb lieber ein EMF Modell verwenden. Das spart dir Arbeit und du musst dir auch nicht mehr überlegen wie man denn nun am besten Property Change Support oder Observer implementiert.
Eclipse Modeling Framework ? Wikipedia

Dafür sollte ein Anfänger aber die benutzen Pattern wenigstens schon mal selber eingesetzt haben, um zu verstehen was ihm alles generiert wird und wie man es einsetzt.
 
Dafuer machst du dich von Eclipse abhaengig und bekommst Probleme, sobald du an die Grenzen vom generierten Code gelangst. Zudem verliert man Refactoring Moeglichkeiten.
Hmm, nein, nein und nein.
EMF wird zwar von Eclipse entwickelt, ist aber Eclipse unabhängig.
Wenn man mehr Funktiontionalität möchte als der generierte Code enthält fügt man sie einfach hinzu, EMF merged das ganze problemlos. Meine Modelle bestehen typischerweise aus 75% generiertem und 25% manuellem Code.
Warum sollte man EMF Modelle nicht refactoren können?
 

Zurück
Oben