FB18 - Das Forum für Informatik

fb18.de / Diplom Informatik / Praktische Informatik (HS)

Beobachter als abstrakte Klasse oder Interface definieren?

Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-28 14:30
bibamba
Fragen über Fragen…
Ist es der einzige Grund dafür, dass wir ein Interface vorziehen, um einer Klasse, die interface implementiert, eventuell eine mehrfache Vererbung (von anderen Interfaces natürlich) zu ermöglichen?
Irgendwie doof gefragt, aber ich hoffe, ihr versteht, was ich meine[12]

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-28 14:45
korelstar
Da eine Klasse (in Java) mehrere Interfaces implementieren, aber nur von einer anderen (ggfs. abstrakten) Klasse erben kann, ist es so gesehen natürlich immer von Vorteil ein Interface zu verwenden, wenn dies möglich ist. Problematisch wird es, wenn man schon eine bestimmte Funktionalität für die erbenden Klassen bereitstellen möchte, da diese Funktionalität dann in der abstrakten Klasse als Methode implementiert wird, was bei einem Interface natürlich nicht geht.

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-28 15:24
bibamba
Ich habe inzwischen im Netz recherchiert und folgende Impl.Lösungen gefunden:
Observer und Observable als Interface definiert.
Observer und Observable als abstrakte Klassen definiert.
Observer als interface und Observable als Klasse (wie in java util)
Ist diese Vielfalt sprachenabhängig?

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-28 15:33
Fred
Die Tatsache, dass Observable eine Klasse und kein Interface ist, ist eine der (vielen) Schwächen von Java. Wie bereits gesagt gibt es so keine Möglichkeit, eine erbende Klasse auch noch Observable zu machen.

Man schreibt sich also entweder seine eigenen Beobachter-Muster-Interfaces, oder man macht es gleich ganz richtig und verwendet Eventing. So wird die Funktionalität des Beobachtens nicht mehr durch Vererbung, sondern durch Komposition erreicht.

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-28 19:40
FireTiger
Und wo genau ist jetzt der Unterschied (außer dem Namen) zwischen Observer und Events?
Ein Observer kann doch genauso delegieren wie ein Event-Empfänger?

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-29 13:14
Fred
Ein Observer kann doch genauso delegieren wie ein Event-Empfänger?
Was genau wird denn da delegiert?

Eine Klasse X kann beliebig viele Event-Objekte speichern, die sie nach aussen hin freigibt (ob nun als public final oder per getter ist egal). Ein oder mehrere Interessenten melden sich dann bei den Events an. Sobald in X etwas interessantes passiert, wird das entsprechente Eventing-Objekt darum gebeten, seine Interessenten zu benachrichtigen. Meinst Du das mit Delegation?

Der Unterschied zum Observer ist, dass beim Eventing die Klasse X selbst KEIN Interface mehr implementiert, wo es um update() oder ähnliches geht. Du meldest Dich nicht direkt bei der Klasse an, sondern bei den Events, die von der Klasse verwaltet werden.

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-29 14:06
FireTiger
Ein Observer kann doch genauso delegieren wie ein Event-Empfänger?
Was genau wird denn da delegiert?

Eine Klasse X kann beliebig viele Event-Objekte speichern, die sie nach aussen hin freigibt (ob nun als public final oder per getter ist egal). Ein oder mehrere Interessenten melden sich dann bei den Events an. Sobald in X etwas interessantes passiert, wird das entsprechente Eventing-Objekt darum gebeten, seine Interessenten zu benachrichtigen. Meinst Du das mit Delegation?

Der Unterschied zum Observer ist, dass beim Eventing die Klasse X selbst KEIN Interface mehr implementiert, wo es um update() oder ähnliches geht. Du meldest Dich nicht direkt bei der Klasse an, sondern bei den Events, die von der Klasse verwaltet werden.
Aber ich brauche dann doch wieder eine Schnittstelle, um auf die Eventing-Objekt zuzugreifen. Das läuft doch wieder auf die Verwendung eines Interface hinaus?

Und die Eventing-Objekte ansich, die haben doch auch so ein Interface implementiert?
Im Prinzip versteckst du doch so doch nur die Observerables hinter einer weiteren Klasse.

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-29 14:18
Fred
Aber ich brauche dann doch wieder eine Schnittstelle, um auf die Eventing-Objekt zuzugreifen. Das läuft doch wieder auf die Verwendung eines Interface hinaus?
Und die Eventing-Objekte ansich, die haben doch auch so ein Interface implementiert?
Klar, jedes Event-Objekt implementiert eine Schnittstelle, ebenso die Interessenten. Bei mir sehen die beiden Interfaces so aus:

public interface Event<P> {     public void subscribe(EventListener<P> listener);     public void unsubscribe(EventListener<P> listener);     public void trigger(P parameter); } public interface EventListener<P> { public void notice(P parameter); }
Um auf die Eventing-Objekte zuzugreifen, benötige ich dagegen kein Interface. Die entsprechende Klasse hat einfach entsprechende getter oder öffentliche Konstanten.

public class Board implements Iterable<Piece> { // ...     public final Event<Object> boardClearedEvent = new SimpleEvent<Object>();     public final Event<List<Piece>> pieceSplitEvent = new SimpleEvent<List<Piece>>();     public final Event<Integer> linesDeletedEvent = new SimpleEvent<Integer>();     public final Event<Piece> pieceInsertedEvent = new SimpleEvent<Piece>();     public final Event<Piece> collisionResolvedEvent = new SimpleEvent<Piece>();     public final Event<Piece> pieceRemovedEvent = new SimpleEvent<Piece>(); // ... }
Und dann kann sich da jemand per
myBoard.linesDeletedEvent.subscribe(new EventListener<Integer>() {     public void notice(Integer parameter)     {         // do something...     } }); anmelden.

Im Prinzip versteckst du doch so doch nur die Observerables hinter einer weiteren Klasse.
Favor composition over inheritance.

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-29 21:14
f0k
Und dann kann sich da jemand per
myBoard.linesDeletedEvent.subscribe(new EventListener<Integer>() {     public void notice(Integer parameter)     {         // do something...     } }); anmelden.
Und per
myBoard.linesDeletedEvent.trigger(...); das Event auslösen. Das finde ich ein bisschen unsauber.

/Edit: Lässt sich natürlich relativ leicht beheben, wenn man noch ein drittes Interface einführt. Ansonsten ist es eine nette Lösung.

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-29 23:25
Fred
Und per
myBoard.linesDeletedEvent.trigger(...); das Event auslösen. Das finde ich ein bisschen unsauber.
Warum sollte man das tun wollen?

/Edit: Lässt sich natürlich relativ leicht beheben, wenn man noch ein drittes Interface einführt. Ansonsten ist es eine nette Lösung.
Genau das hatte ich mal :) Das Event-Interface hatte nur subscribe und unsubscribe, und dann gab es ein Interface Triggerable, welches davon erbte und noch die trigger-Methode hinzugefügt hat. Hat aber letzten Endes alles nur komplizierter gemacht, und ich hab's wieder rausgenommen.

Es hindert Dich ja auch niemand daran, das Event auf Triggerable runterzucasten und dann zu triggern. Letzten Endes kannst Du Dir immer irgendwie in den Fuß schießen.

RE: Beobachter als abstrakte Klasse oder Interface definieren? 2007-07-30 00:11
f0k
Warum sollte man das tun wollen?
Weil's so einfach ist. Es wirkt einfach so, als dürfte jeder, der das Event beobachten darf, auch das Event auslösen. Das Triggerable-Interface als Lösung hatte ich bei meinem Edit auch im Kopf (mit genau dieser Bezeichnung).

Es hindert Dich ja auch niemand daran, das Event auf Triggerable runterzucasten und dann zu triggern. Letzten Endes kannst Du Dir immer irgendwie in den Fuß schießen.
Hmm, stimmt, aber das finde ich dann böswillig. Den anderen Aufruf (obiges Beispiel) nicht. [22]
Hach, die Diskussion erinnert mich ans Teachlet-Seminar [6]