Java Frage zu Observables

ascer

Captain
Registriert
Juni 2008
Beiträge
3.816
Huhu Community



Kurze Implementationsfrage: wenn ich Klassen haben, die von Abstract Observable erben und diese beobachtet werden von Klassen, die das Interface Observer implementieren...wie kann ich dann am besten über mehrere Änderungen informieren und zwischen ihnen differenzieren?

Also ich meine, wenn ich am Observable mit setChanged() die Flag setze und mit notifyObservers() über die Änderung informiere, kann ich ja in ein arg übergeben: notifyObservers( Object arg )

Wäre es dann am schlausten, vorher z.B. immer 'ne enum aufzustellen und die dann zu übergeben?

Was ich meine ist halt: Es wurden mehrere Exemplarvariablen zugleich geändert und der Beobachter braucht die neuen Werte der veränderten Exemplarvariablen.

Z.B. wurden int a, int b und String s verändert und der Observer soll auf alle 3 unterschiedlich reagieren. Dann könnte ich ja nicht jedes mal notifyObservers(a), notifyObservers(b) und notifyObservers(s) machen, da dann die entsprechende
update(Observer o, Object arg) vom Observer jedes Mal diese eine Update-Methode aufrufen würde und nicht unterschiedlich auf die übergebenen Werte reagieren würde/könnte.

Ebenfalls würde auch kein Vergleich helfen, ob arg z.B. ein int ist, da a und b ja vom Typ int sind und auf beide unterschiedlich reagiert werden soll...also würde weder ein Vergleich noch eine überladung von Update was bringen...

...irgendwie müsste doch das Observable am besten über notifyObservers mitteilen, hey: hier kommen mehrere Neuerungen, und zwar folgende..

Wie löst man das am besten?


Grüße & Danke im Voraus

ascer
 
Wie wäre es mit einer Container-Klasse, die alle drei Werte aufnehmen kann?
Und dann wird eine Instanz dieser Klasse übergeben, welche dann a, b und c enthält.

EDIT: Ok, da war jemand schneller :)
 
Das hätte ich auch vorgeschlagen - was mir aus deinem Text jetzt nicht klar wird - werden diese Updatesinfos in der Klasse die observiert wird alle von der selben Methode erzeugt - wenn ja ist das eher ein schlechter Stil - wenn nein dann kannst du alternativ auch eine z.B. "Pair" Klasse bauen die generisch ist - so das du Pair<Typ, Info> übergeben kannst.

Gruß Zoldyck
 
Also z.B. so:

Code:
// irgendwas wird getan
setChanged();
notifyObservers(
    new Object(){
        int a = 12;
        int b = 22;
        String s = "blubb";
    }
);


Oder eignen sich anonyme Klassen dafür nicht so toll?^^




EDIT:


Zoldyck schrieb:
(...)werden diese Updatesinfos in der Klasse die observiert wird alle von der selben Methode erzeugt - wenn ja ist das eher ein schlechter Stil - wenn nein dann kannst du alternativ auch eine z.B. "Pair" Klasse bauen die generisch ist - so das du Pair<Typ, Info> übergeben kannst.

Könntest du das ein wenig erläutern? Mir ist gerade leider nicht klar, wie du das meinst :(
 
Zuletzt bearbeitet:
anonym und Klasse führt das ganze Konzept irgendwie ad absurdum (Klasse = Bauplan)...
Außerdem denke ich du willst irgendwo anders nochmal auf das Objekt zugreifen von daher würde ich das einfach so machen:
Code:
public class ContainerClass{
public int a,b
public String s
public ContainerClass(int a, int b, String s){
this.a=a;
this.b=b;
this.s=s; }

//Methodenaufruf irgendwo
methode(new ContainerClass(42,39,"bla"));

//Methodendefinition
methode(ContainerClass c){
c.a+c.b;//ka was du vorhast
}
 
Ja theoretisch gesehen schon, die Problematik ist nur, dass nicht immer a und b und s geändert werden. Es kann auch vorkommen, dass nur a und b geändert werden und s nicht. Oder gar nur a.

Und würde nicht eigentlich deine Lösung auch mit einer anonymen Klasse funktionieren?



Meine Problematik ist einfach folgende:

Ich habe ein Observable A mit mehreren Exemplarvariablen und einen Observer B. Der Observer B muss über alle Exemplarvariablen vom Observerable A bescheid wissen. Das Problem dabei ist, dass sich in A nicht alle Exemplarvariablen auf ein Mal ändern...es könnte sein dass sich nur eine ändert, oder zwei, oder drei u.s.w.

Auf die verschiedenen Exemplarvariablen muss B aber natürlich unterschiedlich reagieren...

Und B hat doch nur eine Methode update(Observable o, Object arg) die immer aufgerufen wird, egal welche Exemplarvariable von Observable A verändert wurde.

Da aber mit jeder Exemplarvariable etwas unterschiedliches passieren muss in B, muss B wissen, wie viele sich geändert haben und welche explizit, damit er mit jeder der geänderten Exemplarvariablen von A die er bekommt auch das korrekte anstellt...

...und da stellt sich mir halt die Frage, was da die beste Lösung ist?

(man könnte natürlich immer alle Exemplarvariablen immer in gleicher Reihenfolge übergeben, aber das wär ja Mumpitz, bei vielen Exemplarvariablen wird dann ja sehr viel vollkommen unnötig übergeben und bearbeitet...)
 
Setz' in deine Containerklasse noch drei boolean, die angeben, welcher Wert sich geändert hat.
Alternativ könnte man als Kennung, dass sich nichts geändert hat, für String null und int -1 oder MinValue benutzen.
Letzteres hängt natürlich von dem Wertebereich der Variablen ab, den du auch benutzt.

Auch möglich wäre in der Containerklasse nur die booleans zu packen und die tatsächlichen Werte können dann aus Observable o gezogen werden.
 
Du könntest dir auch verschiedene Klassen bauen, die je nach Art der Änderung instanziiert werden und an notifyObservers() übergeben werden. update() prüft dann was für eine Änderung durchgeführt wurde anhand des übergebenen Objektes, castet es dann und hat die entsprechenden Attribute/Methoden zur Verfügung. Beispiel:

Code:
public class Notification {

}

public class SizeNotification extends Notification {
	
	int size;
	
	public SizeNotification(int size) {
		this.size = size;
	}
	
}

public class NameNotification extends Notification {
	
	String name;
	
	public NameNotification(String name) {
		this.name = name;
	}
}

public class Man extends Observable {
	
	int size;
	String name;
	
	public void setSize(int size) {
		this.size = size;
		setChanged();
		notifyObservers(new SizeNotification(size));
	}
	
	public void setName(String name) {
		this.name = name;
		setChanged();
		notifyObservers(new NameNotification(name));
	}
	
}

public class MyObserver implements Observer {
	
	@Override
	public void update(Observable o, Object arg) {
		
		if(arg instanceof NameNotification) {
			System.out.println("Name has changed to " + ((NameNotification) arg).name );
		} else if(arg instanceof SizeNotification) {
			System.out.println("Size has changed to " + ((SizeNotification) arg).size);
		} else {
			System.out.println("Unknown Notification type!");
		}
	}
	
}

/edit

Das wird in dem Beispiel jetzt nicht ganz klar, aber "Notification" sollte eine Oberklasse sein, die Attribute enthält die alle Notifications gemeinsam haben. "NameNotification" und "SizeNotification" haben dann jeweils ihre speziellen Attribute/Methoden.
 
Zuletzt bearbeitet:
Ich übergebe meist nur Konstanten, die das Event identifizieren. Wenn du drei verschieden Möglichkeiten hast würde sich in etwa soetwas anbieten:
Code:
dataChanged(DataEvent e) {
    short mask = e.getMask();
    if(mask & DataEvent.A_CHANGED != 0) {...}
    if(mask & DataEvent.B_CHANGED != 0) {...}
    if(mask & DataEvent.C_CHANGED != 0) {...}
}

müsstest du halt eigene Observer erstellen, aber ich find das so schicker, weil man mit einem Observer viele verschiedene Events unterstützen kann (64 wenn die gleichzeitig auftreten können, 2^64 wenn die nur einzeln sind :D

EDIT: fehler im code korrigiert

EDIT2: man kann auch ganz ohne das Event auskommen, primitive tuns da ja auch.
 
Zuletzt bearbeitet:
Zurück
Oben