Java Standard: Muster Observer

Aus Wikibooks

Wechseln zu: Navigation, Suche
Zurück zu Muster | Hoch zu Java Inhaltsverzeichnis | [[{{{vorlink}}}|Vor zu ]]


Inhaltsverzeichnis

[Bearbeiten] Beobachter

Informiert über Änderungen eines Objektes (vergleiche WikiBook Muster).

[Bearbeiten] Implementierung (1) - do it yourself

import java.util.ArrayList;
 
public class Subjekt {
 
  private ArrayList<Beobachter> beobachter = new ArrayList<Beobachter>();
 
  private Object zustand = null;
 
  private void benachrichtigen() {
    for (Beobachter b : beobachter)
      b.aktualisiere();
  }
 
  public void entferne(Beobachter b) {
    beobachter.remove(b);
  }
 
  public Object gibZustand() {
    return zustand;
  }
 
  public void registriere(Beobachter b) {
    beobachter.add(b);
  }
 
  public void setzeZustand(Object neu) {
    zustand = neu;
    benachrichtigen();
  }
 
}
public interface Beobachter {
  public void aktualisiere();
}
 public class KonsolenBeobachter implements Beobachter {
   protected Subjekt subjekt = null;
 
   public void setzeSubjekt(Subjekt s) {
     if (this.subjekt != null)
       this.subjekt.entferne(this);
 
     this.subjekt = s;
 
     if (this.subjekt != null)
       this.subjekt.registriere(this);
   }
 
   public void aktualisiere() {
     System.out.println(this.subjekt.gibZustand());
   }
 }
 public class GeschwaetzigerKonsolenBeobachter extends KonsolenBeobachter {
   public void aktualisiere() {
     System.out.println("Das Subjekt hat seinen Zustand geaendert; jetzt: " + this.subjekt.gibZustand());
   }
 }
 public class BeobachterTest {
   public static void main(String[] args) {
     Subjekt s = new Subjekt();
     KonsolenBeobachter b1 = new KonsolenBeobachter();
     KonsolenBeobachter b2 = new GeschwaetzigerKonsolenBeobachter();
 
     b1.setzeSubjekt(s);
     b2.setzeSubjekt(s);
 
     s.setzeZustand("Hallo Welt");
     b2.setzeSubjekt(null);
     s.setzeZustand("Hallo schoene Welt");
   }
 }

[Bearbeiten] Implementierung (2) - java.util.Observer, java.util.Observable

public class Beobachter implements Observer {
 private static int NR = 1;
 private int nr;
 
 public Beobachter() {
   this.nr = Beobachter.NR++;
 }
 
 public void update(Observable beobachtbarer, Object text) {
   System.out.println("Beobachter " + nr + " meldet: Text=" + text);
 }
}


public class Beobachtbarer extends Observable {
 private String text;
 
 public Beobachtbarer() {
   super();
 }
 
 public void setText(String text) {
   this.text = text;
   super.setChanged(); // Markierung, daß sich der Text geändert hat
   super.notifyObservers(text); // ruft für alle Beobachter die update-Methode auf
 }
 
 public String getText() {
   return text;
 }
}


public class Beobachtungen {
 public static void main(String[] args) {
   Beobachter[] bArray = {new Beobachter(), new Beobachter(), new Beobachter()};
   Beobachtbarer bb = new Beobachtbarer();
   for (Beobachter b: Arrays.asList(bArray)) {
     bb.addObserver(b);
   }
   bb.setText("Ich");
   bb.setText("werde");
   bb.setText("beobachtet.");
 }
}


/*
Ausgabe:
********
Beobachter 3 meldet: Text=Ich
Beobachter 2 meldet: Text=Ich
Beobachter 1 meldet: Text=Ich
Beobachter 3 meldet: Text=werde
Beobachter 2 meldet: Text=werde
Beobachter 1 meldet: Text=werde
Beobachter 3 meldet: Text=beobachtet.
Beobachter 2 meldet: Text=beobachtet.
Beobachter 1 meldet: Text=beobachtet.
*/

[Bearbeiten] Erläuterungen

Ein Observer (Beobachter) kann über seine update-Methode auf Änderungen eines Observable (Beobachtbarer) reagieren. Das passiert jedoch nur, wenn sich Observer an Observable registrieren.

In unserer Beispiel-Implementierung wird in der update-Methode von Beobachter lediglich eine Info auf die Konsole geschrieben. Die Klasse Beobachtbarer besitzt nur eine Set-Methode, über die ein Text verändert werden kann. Dabei wird der geänderte Text immer mittels der setChanged-Methode als "geändert" markiert und über die notifyObservers-Methode wird bei allen registrierten Observer-Objekten die update-Methode aufgerufen.

Die zentrale Klasse Beobachtungen vereint nun Observer und Observable. Wir sind maßlos und haben gleich drei Beobachter bei dem Beobachtbarer registriert. Jeder Aufruf der setText-Methode bewirkt nun den Aufruf der update-Methode bei allen drei Beobachter-Objekten.

[Bearbeiten] Implementierung (3) - java.beans.PropertyChangeListener / java.beans.PropertyChangeSupport

public class AktualisierungsListener implements PropertyChangeListener {
 public void propertyChange(PropertyChangeEvent pce) {
   System.out.println("Bei der " + pce.getSource() + " wurde der Parameter \"" + 
       pce.getPropertyName() + "\" von \"" + pce.getOldValue() + 
       "\" auf \"" + pce.getNewValue() + "\" geaendert.");
 }
}


public class Quelle {
 private String text;
 private int zahl;
 
 public void setText(String text) {
   this.text = text;
 }
 
 public void setZahl(int zahl) {
   this.zahl = zahl;
 }
 
 public String getText() {
   return text;
 }
 
 public int getZahl() {
   return zahl;
 }
 
 public String toString() {
   return "Quell-Bean";
 }
}

public class Aktualisierbarer extends PropertyChangeSupport {
 private Quelle quelle;
 
 public Aktualisierbarer(Quelle quelle) {
   super(quelle);
   this.quelle = quelle;
 }
 
 public void setText(String text) {
   super.firePropertyChange("text", quelle.getText(), text);
   quelle.setText(text);
 }
 
 public void setZahl(int zahl) {
   super.firePropertyChange("zahl", quelle.getZahl(), zahl);
   quelle.setZahl(zahl);
 }
 
 public String getText() {
   return quelle.getText();
 }
 
 public int getZahl() {
   return quelle.getZahl();
 }
}


public class Aktualisierungen {
 public static void main(String[] args) {
   Aktualisierbarer aktu = new Aktualisierbarer(new Quelle());
   aktu.addPropertyChangeListener(new AktualisierungsListener());
   aktu.setZahl(7);
   aktu.setText("vorher");
   aktu.setText("jetzt");
   aktu.setZahl(13);
 }
}


/*
Ausgabe:
********
Bei der Quell-Bean wurde der Parameter "zahl" von "0" auf "7" geaendert.
Bei der Quell-Bean wurde der Parameter "text" von "null" auf "vorher" geaendert.
Bei der Quell-Bean wurde der Parameter "text" von "vorher" auf "jetzt" geaendert.
Bei der Quell-Bean wurde der Parameter "zahl" von "7" auf "13" geaendert.
*/


[Bearbeiten] Erläuterungen

Über den AktualisierungsListener werden die Inhaltsänderungen von Objekten (hier: Quell-Bean) überwacht und es kann darauf reagiert werden. In unserem Beispiel wird hier lediglich eine Ausgabe auf die Konsole gemacht.

Unsere Quelle (Quell-Bean) besitzt 2 Attribute, die gesetzt werden können. Mit dem Aktualisierbarer werden diese Setz-Möglichkeiten überwacht. In jeder seiner Set-Methoden wird ein Attribut-Änderungs-Event ausgelöst.

Die zentrale Klasse Aktualisierungen vereint nun AktualisierungsListener und Aktualisierbarer, damit die Attribut-Änderungen der Quell-Bean auch bemerkt werden.



Zurück zu Muster | Hoch zu Java Inhaltsverzeichnis | [[{{{vorlink}}}|Vor zu ]]
Persönliche Werkzeuge
Buch erstellen
  • Artikel hinzufügen
  • Hilfe zu Sammlungen