FB18 - Das Forum für Informatik

fb18.de / Off-Topic / Hard- und Softwarefragen

Beobachter-Muster in Java

Beobachter-Muster in Java 2006-08-06 16:27
korelstar
Die von Sun mitgelieferte Implementierung des Entwurfmusters Beobachter in java.util.Observer und java.util.Observable finde ich nicht so schick, da sie nicht Generics benutzen (außerdem ist es häufig unnötig dem Beobachter noch den Beobachteten als Objekt zu übergeben). Gibt es irgendwo im aktuellen JRE ein Interface, das isomorph zu folgendem Code ist (meinetwegen kann da auch noch der Beobachtete zusätzlich übergeben werden)?

public interface Beobachter<T> { public void benachrichtige(T objekt); }
Klar kann ich dieses Interface auch selbst schreiben. Mehr als das da oben soll es ja gar nicht haben. Aber ich fände es schöner, für so einen Zweck auf überall verfügbare Klassen zurückzugreifen, anstatt in jeder Software dieses Interface mitzuschleppen. Wird java.util.Observer vielleicht in der nächsten Version Generics benutzen?

Re: Beobachter-Muster in Java 2006-08-06 18:19
Anonymer User
Wird java.util.Observer vielleicht in der nächsten Version Generics benutzen?
Wozu? Generics bieten Dir hier keinen Gewinn.

LEIFer

Re: Beobachter-Muster in Java 2006-08-06 18:48
korelstar
Generics bieten Dir hier keinen Gewinn.
Warum nicht? Ich fände es schon ganz interessant als Beobachter zu wissen, dass ich nur Objekte eines bestimmten Typs in der Benachrichtigung erhalte. Bisher bleibt mir nur eine Vereinbarung mit dem Beobachteten zu treffen, die der Compiler nicht prüfen kann.

Re: Beobachter-Muster in Java 2006-08-06 22:28
tekai
Generics bieten Dir hier keinen Gewinn.
Warum nicht? Ich fände es schon ganz interessant als Beobachter zu wissen, dass ich nur Objekte eines bestimmten Typs in der Benachrichtigung erhalte. Bisher bleibt mir nur eine Vereinbarung mit dem Beobachteten zu treffen, die der Compiler nicht prüfen kann.

Vielleicht verstehe ich dich nicht ganz, aber für das Beobachter-Muster oder EventListener braucht man nur ein Interface das der Beobachter implementiert und in dem kann man ja festelegen für welche Events sich der Beobachter/Listener interessiert

public interface SpecificEventlistener { public void processEvent(SpecificEvent); }
abgesehen ist aufgrund der Einfachvererbung in Java die Klasse Observable ziemlich beschränkt. Wenn du unbedingt eine Referenz zu dem Observer brauchst würde ich sie lieber in das Event packen.

Re: Beobachter-Muster in Java 2006-08-06 23:53
korelstar
Vielleicht verstehe ich dich nicht ganz, aber für das Beobachter-Muster oder EventListener braucht man nur ein Interface das der Beobachter implementiert und in dem kann man ja festelegen für welche Events sich der Beobachter/Listener interessiert
Ja, ein eigenes Interface habe ich oben ja auch angegeben. Ich schrieb aber auch, warum ich ein bereits verfügbares lieber nutzen würde.

abgesehen ist aufgrund der Einfachvererbung in Java die Klasse Observable ziemlich beschränkt.
Einen Observable benötigt man ja gar nicht immer. Im konkreten Fall erhält eine Methode als Parameter eine Referenz auf einen Beobachter und sendet dann während ihrer Ausführung zu bestimmten Anlässen ein Objekt eines bestimmten Types. Ich möchte dass dieser Typ festgelegt ist, und nicht einfach nur Object ist. Daher ist das o.a. Interface praktisch. Jetzt suche ich sowas im JRE. java.util.Observer kommt dem recht Nahe, lässt sich aber nicht auf einen Typ festlegen, wie es durch Generics ginge.

Wenn du unbedingt eine Referenz zu dem Observer brauchst würde ich sie lieber in das Event packen.
Nein, diese Referenz benötige ich ja gar nicht, wie ich schrieb. Mir geht es um den zweiten Parameter in Observer.update(Observable, Object). Ich würde es bevorzugen, wenn der mit Generics realisiert wäre, wie in meinem Code-Beispiel. Den ersten Parameter kann man ja zur Not auf null setzen.

Edit: Okay, ich sollte das wohl über eigene Klassen realisieren, die von EventObject und EventListener erben. Aber warum soviel Arbeit? Hier wäre doch auch sowas wie ein EventListener<E extends EventObject> angebracht, das über eine Benachrichtigungsmethode verfügt, die ein Objekt vom Typ E übermittelt. Dann muss man nicht unnötig viele Interfaces erstellen.

Re: Beobachter-Muster in Java 2006-08-07 14:24
Anonymer User
Hmmm. Okay, ja, ich hatte nicht gleich verstanden, warum das sinnvoll wäre.

Es gibt einen Bugreport "Adding generics to all *Event classes", in dem auch ein Observer<E> gefordert wird. Der Bug ist aber schon zwei Jahre alt und steht auf "In progress, request for enhancement" ohne dass es im letzt en Jahr noch einen Kommentar dazu gab.

In einem Bugreport zu einem anderen Thema heißt es "Observable has fallen into disuse and is no longer under active development."

Möglicherweise liegt hier auch wirklich ein Grund: Observer/Observable wurde in JDK 1.0 eingeführt. Mit EventObject/EventListener wurden im JDK 1.1 andere Typen als Observer zur Benachrichtigung eingeführt. EventListener ist nur noch ein Marker-Interface, da man a) damals noch keine Generics hatte und b) so auch mehrere Methoden haben kann, die über ein Ereignis informieren. Mehrere Methoden bringen nebenher auch informativere Methodennamen mit (keyPressed, keyReleased).

Würde man EventListener mit einem Typen parametrisieren, so würde das (im Gegensatz zu Observer) erst einmal wenig bringen, da es eben nur ein Marker-Interface ist. Dort auch gleich noch eine Methode eventHappened(E event) einzuführen ist nicht möglich, da man dadurch API-inkompatibel wird. Bliebe also noch eine völlig neue Klasse oder Unterklasse von EventListener: GenericEventListener<E extends EventObject>.

Damit hätte man dann aber drei unterschiedliche Benachrichtigungsmechanismen im JDK. Das will Sun vielleicht vermeiden.

LEIFer

Re: Beobachter-Muster in Java 2006-08-07 21:00
korelstar
Danke für die Antwort.

Ich finde es allerdings nicht ganz schlüssig zu sagen, dass Observer/Observable nun nicht mehr benutzt wird/werden soll und es wegen dieser Ausrede nicht mehr zu ändern, ohne die beiden als Deprecated zu markieren. Es würde schließlich keine Arbeit sein, das Interface und die Klasse anzupassen und kompatibel wäre es obendrein auch. Naja, können wir wohl nicht ändern.

Eine Unterklasse GenericEventListener<E extends EventObject> mit einer Methode wäre doch gar kein neuer Benachrichtigungsmechanismus, sondern würde nur auf dem bisherigen EvenListener-System aufbauen. Fände ich nicht widersprüchlich sondern erleichternd. Naja, muss ich wohl weiter eigene Interfaces verteilen.