Servus,
bei meinem jetzigen Projekt hatte ich ursprünglich die Idee, einen Großteil der internen Kommunikation über ein Signalsystem zu realisieren. Es gibt eine GUI und einen Backend-Bereich, und sehr oft treten Ereignisse auf, die an mehreren Stellen von Bedeutung sind. Jede Klasse, die solche Benachrichtigungen braucht, hätte sich dann einfach für ein bestimmtes Signal bzw. für eine bestimmte Gruppe von Signalen registriert.
Mein Kollege meinte aber, ich soll bloß die Finger von Signalen lassen und lieber Listener verwenden, da das sauberer getrennt ist und so ein zentrales Signalsystem sehr schnell alles "zumüllt". Da mir das zunächst eingeleuchtet hat, habe ich dann auch für jeden Zweck einen eigenen Listener definiert, aber mittlerweile bin ich der Meinung, daß das viel mehr "zugemüllt" hat, als wenn ich Signale verwendet hätte (die Größe des Projekts ist meiner Meinung nach auch noch klein genug, daß Signale nicht großartig problematisch gewesen wären).
Ursprünglich wollte ich diese Listener irgendwie generisch anlegen, und das hat nicht funktioniert. Möglicherweise wäre es, wenn es denn doch ginge, weitaus übersichtlicher. Allerdings gibt's da eben ein Problem:
Hier mal ein typisches Beispiel, wie bei mir ein Listener/Sender-Paar aussieht:
Mein Traum wäre es jetzt, diesen Code nur ein einziges mal zu benötigen und ihn über <generische Parameter> an die jeweilige Message anzupassen. Das hieße also, ich würde "PlayerMessage" von einem allgemeinen "Message"-Typ ableiten. Nun funktioniert das auch für den Listener, den ich als public interface AudioPlayerListener<T extends Message> deklarieren würde. Allerdings hakt es dann beim Sender, denn der Sender besitzt ja eine Liste seiner Listener, und diese wird zwar ebenfalls parametrisiert, allerdings hat sie einen eindeutigen Namen - was letztendlich verhindern würde, daß man eine Klasse von mehreren Sendern ableiten könnte.
Die einzige Lösung hierfür wäre, einen einzigen Sender zu definieren, der dann eben auch sämtliche Arten von Messages durchschicken könnte. Allerdings ist das dann wieder sehr großzügig, weil der Sender nun "allmächtig" ist, und die Ordentlichkeit wäre wiederum zerstört. Außerdem müßte dieser eine einzige Liste mit allen möglichen Listenern halten, und bei jeder Benachrichtigung eines Listeners zunächst dessen Message-Typ überprüfen.
Ich habe schon die verschiedensten Konstellationen durchprobiert, aber es hängt dann letztendlich immer an irgendeiner Stelle. Hat jemand von euch schonmal erfolgreich solch ein Listener/Sender-Paar hingekriegt, das vollkommen generisch arbeiten kann und "sauber" ist? Oder sollte man doch lieber Signale verwenden?
bei meinem jetzigen Projekt hatte ich ursprünglich die Idee, einen Großteil der internen Kommunikation über ein Signalsystem zu realisieren. Es gibt eine GUI und einen Backend-Bereich, und sehr oft treten Ereignisse auf, die an mehreren Stellen von Bedeutung sind. Jede Klasse, die solche Benachrichtigungen braucht, hätte sich dann einfach für ein bestimmtes Signal bzw. für eine bestimmte Gruppe von Signalen registriert.
Mein Kollege meinte aber, ich soll bloß die Finger von Signalen lassen und lieber Listener verwenden, da das sauberer getrennt ist und so ein zentrales Signalsystem sehr schnell alles "zumüllt". Da mir das zunächst eingeleuchtet hat, habe ich dann auch für jeden Zweck einen eigenen Listener definiert, aber mittlerweile bin ich der Meinung, daß das viel mehr "zugemüllt" hat, als wenn ich Signale verwendet hätte (die Größe des Projekts ist meiner Meinung nach auch noch klein genug, daß Signale nicht großartig problematisch gewesen wären).
Ursprünglich wollte ich diese Listener irgendwie generisch anlegen, und das hat nicht funktioniert. Möglicherweise wäre es, wenn es denn doch ginge, weitaus übersichtlicher. Allerdings gibt's da eben ein Problem:
Hier mal ein typisches Beispiel, wie bei mir ein Listener/Sender-Paar aussieht:
Code:
public interface AudioPlayerListener
{
public void eventOccured(PlayerMessage msg, AudioPlayerListenerSender sender);
public class PlayerMessage
{
public enum Type
{
PLAY,
STOP,
PAUSE,
REPOSITIONED,
END_OF_MEDIA,
TRACKS_ADDED,
TRACKS_REMOVED,
KILL,
}
public Type type;
public AudioTrack track;
public PlayerMessage(Type type)
{
this.type = type;
}
public PlayerMessage(Type type, AudioTrack track)
{
this.type = type;
this.track = track;
}
}
public abstract class AudioPlayerListenerSender
{
private HashSet<AudioPlayerListener> _audioPlayerListeners = new HashSet<AudioPlayerListener>();
private PlayerMessage _message;
public void addAudioPlayerListener(AudioPlayerListener l)
{
_audioPlayerListeners.add(l);
}
public void removeAudioPlayerListener(AudioPlayerListener l)
{
_audioPlayerListeners.remove(l);
}
protected void sendMessage(PlayerMessage msg)
{
for(AudioPlayerListener l : _audioPlayerListeners)
l.eventOccured(msg, this);
}
protected void sendMessageWithoutBlocking(PlayerMessage msg)
{
_message = msg;
new Thread()
{
@Override
public void run()
{
sendMessage(_message);
}
}.start();
}
}
}
Mein Traum wäre es jetzt, diesen Code nur ein einziges mal zu benötigen und ihn über <generische Parameter> an die jeweilige Message anzupassen. Das hieße also, ich würde "PlayerMessage" von einem allgemeinen "Message"-Typ ableiten. Nun funktioniert das auch für den Listener, den ich als public interface AudioPlayerListener<T extends Message> deklarieren würde. Allerdings hakt es dann beim Sender, denn der Sender besitzt ja eine Liste seiner Listener, und diese wird zwar ebenfalls parametrisiert, allerdings hat sie einen eindeutigen Namen - was letztendlich verhindern würde, daß man eine Klasse von mehreren Sendern ableiten könnte.
Die einzige Lösung hierfür wäre, einen einzigen Sender zu definieren, der dann eben auch sämtliche Arten von Messages durchschicken könnte. Allerdings ist das dann wieder sehr großzügig, weil der Sender nun "allmächtig" ist, und die Ordentlichkeit wäre wiederum zerstört. Außerdem müßte dieser eine einzige Liste mit allen möglichen Listenern halten, und bei jeder Benachrichtigung eines Listeners zunächst dessen Message-Typ überprüfen.
Ich habe schon die verschiedensten Konstellationen durchprobiert, aber es hängt dann letztendlich immer an irgendeiner Stelle. Hat jemand von euch schonmal erfolgreich solch ein Listener/Sender-Paar hingekriegt, das vollkommen generisch arbeiten kann und "sauber" ist? Oder sollte man doch lieber Signale verwenden?