# Observer und Observable



## H3llGhost (30. Oktober 2009)

Hallo Leute,

ich habe von Wikipedia den Artikel zum Observer gelesen. (Link: Observer (Entwurfsmuster) ? Wikipedia)
Ich habe dementsprechend auch mein Interface Observable geschrieben, die Klasse ObservableSupport und meine Klasse mit einem implements erweitert.
Mein Problem ist nun, dass ich nicht weiß wie ich mit folgendem Aufruf weiterarbeiten kann:


```
public void update(Observable arg0, Object arg1) {
		System.out.println(arg0);
		System.out.println(arg1);
//		if ((arg0 == this.s || arg0 == this.fs) && "gui".equals(arg1)){
//			if (arg0 == this.s) {
//				if(this.s.getProperty().startsWith("Client-"))
//					this.clientEvent(this.s.getProperty());
//				else
//					this.writeLog(this.s.getProperty());
//			} else if (arg0 == this.fs) {
//				if(this.fs.getProperty().startsWith("Client-"))
//					this.clientEvent(this.fs.getProperty());
//				else
//					this.writeLog(this.fs.getProperty());
//			}
//		}
	}
```

Als Kommentar sieht man mein altes Handling, dies ist nun nicht mehr funktionstüchtig, da ich nun das Interface benutze.

Habt ihr eventuell ne Idee wie ich damit weiterarbeiten kann?
Als Hinweis die Ausgabe von arg0 und arg1 ergibt folgendes:



> observer.ObservableSupport@e2291
> gui



Vielen Dank im Vorraus.


----------



## kabel2 (30. Oktober 2009)

Huch, keine Delegates? Ach ja, das ist ja Java 

Mit dem Interface weiterarbeiten geht, der Code müsstest zuerst prüfen, welches Subjekt die Nachricht gesendet hat, und dann entsprechend dem Grund geeignet reagieren.
Wenn ObservableSupport eine Hilfsklasse ist, die von einem Subjekt gehalten wird (also Delegation statt Vererbung), dann muss die Identifikation anders hergestellt werden;
der ObservableSupport könnte z.B. das Subjekt wissen, an dem dieser hängt. 
Eine andere Möglichkeit bestünde darin, dass der mitgelieferte Änderungsgrund Rückschlüsse auf das Subjekt erlaubt ... das bereitet aber früher oder später garantiert Ärger 

Das Observable selber als Argument macht nur Sinn, wenn erwartet wird, dass es Beobachter gibt, die mehrere Subjekte gleichzeitig beobachten.
Wenn dem nicht so ist, würde eine #Update() Methode reichen, die evtl. noch den Grund des Aufrufes mitliefert -- in welcher Form auch immer.
Strings sind halt hübsch allgemein, aber da kann man sich ganz schnell ganz fies ins Knie schießen mit.


----------



## H3llGhost (2. November 2009)

Ich habe mir das alles mal über das Wochenende angeschaut, aber wenn ich ehrlich bin ich habe es nicht geschafft. 

Kannst du mir eventuell noch einen Tipp geben?


----------



## RoCMe (2. November 2009)

Hi!



> Ich habe dementsprechend auch mein Interface Observable geschrieben, die Klasse ObservableSupport und meine Klasse mit einem implements erweitert.



Hm, hast du wirklich ein eigenes Interface Observable geschrieben, oder hast du das von Java genutzt? Und wer ist ObservableSupport? 

"meine Klasse" und ObservableSupport implementieren das Interface "Observable"?

Ich hab das Gefühl, ich versteh nicht so ganz, wo dein Problem liegt... Ich schlage als Lösung einfach mal einen cast vor, ohne genau zu wissen, ob dir das hilft 


```
public void update(Observable arg0, Object arg1) {
        System.out.println(arg0);
        System.out.println(arg1);
        if (arg0 instanceof WAS_AUCH_IMMER.class) {
            WAS_AUCH_IMMER myDingsDa = (WAS_AUCH_IMMER) arg0;
            if (myDingsDa.getProperty().startsWith("Client-"))
                    this.clientEvent(myDingsDa.getProperty());
            else
                  this.writeLog(myDingsDa.getProperty());
       }
}
```

In der Annahme, dass this.s und this.fs entweder Instanzen der gleichen Klasse sind oder zumindest die Methode getProperty() von der gleichen Superklasse erben, kannst du im obigen Codebeispiel "WAS_AUCH_IMMER" durch die entsprechende Klassenbezeichnung ersetzen.

Hoffe, das löst dein Problem 

Gruß,

RoCMe


----------



## H3llGhost (2. November 2009)

Meinen Code habe ich aus dem Wikipedia Artikel aus dem ersten Post.

Ich poste ihn hier aber nochmal:

ObservableSupport

```
import java.util.Observable;
 
public class ObservableSupport extends Observable {
	public ObservableSupport() {
	}
	public void markAndNotify(Object o){
		setChanged();
		notifyObservers(o);
	}
}
```

Observable

```
import java.util.Observer;
 
public interface Observable {
    void addObserver(Observer o);
    void deleteObserver(Observer o);
    void deleteObservers();
    boolean hasChanged();
    int countObservers();
}
```


----------



## kabel2 (3. November 2009)

Vergiss den Code mit dem ObservableSupport. Das ist Schrott; interfaces werden implementiert, und der Code ist unvollständig. 
Außerdem ist das ist einfach der Versuch, den PropertyChangeListener nachzubauen.


```
public class Subjekt {

	public static final String VALUE_CHANGED = "Subjekt_value";
	
	public Subjekt () {
		m_value = 100;
		m_pcs = new PropertyChangeSupport(this);
	}
	
	public void change() {
		int oldValue = m_value;
		m_value --;
		m_pcs.firePropertyChange(VALUE_CHANGED, oldValue, m_value);
	}
	
	public void AddListener(PropertyChangeListener l) {
		m_pcs.addPropertyChangeListener(l);
	}
	
	public void RemoveListener(PropertyChangeListener l) {
		m_pcs.removePropertyChangeListener(l);
	}
	
	private int m_value;
	
	private PropertyChangeSupport m_pcs;
	
}

public class Beobachter implements PropertyChangeListener {
	
	public Beobachter(Subjekt s) {
		m_subjekt = s;
	}
	
	public static void main(String[] args) {
		Subjekt s = new Subjekt();
		Beobachter b = new Beobachter(s);
		b.attach();
		s.change();
		b.detach();
	}
	
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if(Subjekt.VALUE_CHANGED.equals(evt.getPropertyName())) {
			System.out.println("Value changed from " + evt.getOldValue() + " to " + evt.getNewValue());
		}
	}
	
	public void attach() {
		m_subjekt.AddListener(this);
	}
	
	public void detach() {
		m_subjekt.RemoveListener(this);
	}
	
	private Subjekt m_subjekt;

}
```

Der Code muss da garnix rumcasten, denn es ist ja bekannt, wer den property change gefeuert hat.
Jetzt ist hier aber nur eine Subjekt-Instanz. Wenn es davon mehrere gibt, ist erstmal nicht bekannt, welche Subjekt-Instanz gefeuert hat - dafür gibts dann die Methode #getSource() am PropertyChangeEvent.

Variationsmöglichkeiten:

Der Beobachter muss PropertyChangeListener nicht implementieren, er könnte auch eine anonyme Klasse dafür verwenden.
Der Beobachter muss nicht auf alle property changed events des Subjekts hören.
Man könnte noch etwas mit Generics spielen, damit beim property change die Instanz mit ihrem statischen Typ übergeben wird, und nicht bloß als Object.
 ... und sicher noch vieles anderes ...

Hock Dich mal mitm Debugger in die main() und step durch.


----------

