W / o Funktionszeiger, was ist eine empfehlenswerte Art und Weise Rückruf in Java zu implementieren - anders als Schnittstellen?

StackOverflow https://stackoverflow.com/questions/626669

  •  06-07-2019
  •  | 
  •  

Frage

Ich habe ein paar Klassen, die einander einige Informationen weitergeben wollen und später wieder aufgerufen werden, dass die Informationen (Callback-Muster) verwendet wird.

Im Rahmen meiner Anwendung dieser Mechanismus dient zwei Zwecken:

  • geplant / verzögerte Ausführung
  • asynchrone Ausführung beteiligt Messaging

Meine Objekte im Grunde sagen einander „wenn Sie X fertig zu tun, rufen Sie mich zurück und sagen Sie mir, Y mit Z zu tun (weil ich es bis dahin vergessen werden)“ . Wo X könnte nur auf den richtigen Zeitpunkt warten, sondern auch mit einem Remote-Service oder rufen Sie eine lokale Funktion in Verbindung steht.

Nun wurden Funktionszeiger (oder gleichwertig) in Java, ich würde etwas „Job“ Klasse implementieren, die ein Plus der Argumente, die sie braucht. Zum Beispiel in PHP würde diese Struktur hat einen Klassennamen zu speichern, einen Funktionsnamen und eine Reihe von Argumenten. In C, wäre es ein Zeiger auf die Funktion sein, und ich würde die Argumente die gleiche Anzahl und Art für alle Anrufe machen.

In Java, ist die übliche Vorgehensweise ist eine Schnittstelle zu haben, die von allen Klassen implementiert ist, die zurück wollen, wie folgt aufgerufen werden:

public interface ICallable {
    public void call_me(Object data);
}

Nun würde das für mich nicht, weil

  • , um die Objekte zurückgerufen werden könnten, eine andere Gruppe von Methoden haben den Anruf anzunehmen
  • der Anrufer nicht derjenige zu entscheiden, welche Anruf vorgenommen werden sollen

Vielleicht mein Problem ist, dass ich eine gemeinsame Datenstruktur zu haben, ich versuche, und für die verschiedenen Rückrufe Aufrufprozedur, aber im Prinzip, so scheint es mir sinnvoll zu machen.

Was ist ein gutes Design-Muster, diese Situation in Java zu nähern?

War es hilfreich?

Lösung

Ich glaube, Sie werden feststellen, dass eine Schnittstelle die beste Lösung ist. Ich verstehe nicht, Ihren Widerspruch zu ihnen. Wenn der Empfänger eine andere Methode aufgerufen haben muss, haben dann die Schnittstelle Methode, um die unterschiedliche Methode aufrufen.

Wenn Ihr Receiver Klasse mehrere Handler haben muss, können Sie anonyme innere Klassen verwenden, die die Schnittstelle implementieren, eine für jede Art von Handler Sie benötigen. Zum Beispiel, wenn der Absender eine Schnittstelle namens „ListenerInterface“ verwendet, Ihr Empfänger könnte eine anonyme innere Klasse definieren, die die ListenerInterface und rufen die Empfänger-Methode „handler“ implementiert.

   sender.addListener(new ListenerInterface()
   {
      public void callback(Object arg)
      {
         handlerFunction(arg);
      }
   });

Andere Tipps

Sie könnten ein Konzept unter Verwendung ähnlich wie anonyme innere Klassen

Eine weitere Referenz hier

Ich würde eine Schnittstelle verwenden, wie Sie beschrieben haben, und dann eine anonyme Klasse für Ihre Rückrufe verwenden. Zum Beispiel aus Ihrem Anrufer:

ICallback callback = new ICallback() { 
    public void call_me(Object data) { this.actionToCall(data); }
}
serverObject.doX(callback);

(Die Syntax etwas anders sein kann als das.)

Auf diese Weise können in dem ursprünglichen Anrufer (an der Stelle des Anrufs) können festlegen, welche Maßnahmen zu ergreifen, wenn Sie fertig sind.

Wenn Sie wirklich nicht wollen, Schnittstellen verwenden (und mir vertrauen Sie tun!) Sie Reflektion verwenden könnte die Methode, die Sie genannt haben wollen zu bekommen und geben sie dann an die eine, die die Berufung tun muss. Das ist so nah an einen C Funktionszeiger wie Sie gehen zu bekommen.

Reflection wird langsamer sein (wahrscheinlich) als die Schnittstelle Art und Weise, es zu tun (aber das spielt keine Rolle, es sei denn, es häufig genannt wird).

Reflection wird nicht die Kompilierung Typüberprüfung hat, dass die Schnittstelle Art und Weise, es zu tun hat (was bedeutet, dass Sie zur Laufzeit zum Absturz bringen könnten).

Reflection wird hässlicher Code als die Schnittstelle, wie es auch zu tun.

Aber wenn Sie wirklich wirklich wirklich wollen Zeiger C Funktion simulieren dann Reflexion ist so nah wie Sie bekommen werden.

Rückrufe sind eine allgemeine Idee, und Sie sollten keine one-size-fits-all-Schnittstelle versuchen. Machen Sie Ihren Callback-Schnittstelle zum Einsatz spezifisch. Es sollte die Semantik des Typs übereinstimmen, die es zu übergeben wird und das macht die Rückrufe. Die übliche Implementierung der Callback-Schnittstelle würde als eine anonyme innere Klasse erfolgen. Widerstehen Sie der Versuchung, die Schnittstelle in einer äußeren Klasse zu implementieren, was zu einer inkohärenten Art.

ich das Problem sein Missverständnis, aber es scheint mir, Sie von der Einrichtung eine Art von Event-System profitieren würden.

Im Grunde legen Sie einen Event-Handler und die Klassen auf, die wissen möchten, über das Ereignis an den Event-Handler abonnieren. Also für Ihr Problem, wenn X erfolgt wäre es ein FinishedProcessingEvent Feuer (), die Ihr Objekt abonniert werden würde. Wenn Ihr Objekt dieses Ereignis empfängt (zusammen mit allen anderen Teilnehmern, die über die Veranstaltung kümmern) es wird die richtige Aktion (Y mit Z) zu tun. Diese Aktionen sind definiert innerhalb der Objekte so unterschiedliche Objekte könnten verschiedene Dinge tun, auf der Grundlage der gleichen Ereignisse.

Ist diese Hilfe?

Ich bin sicher, dass es einige interessante Muster, das Ihr Problem löst, aber ich würde die simple minded Ansatz Infrastruktur wählen. Stuffing Anfragen und Antworten in einer Nachrichtenwarteschlange, wie JMS, Ihr System könnte einfacher und robuster sein, weil Sie Ereignisse nehmen Sekunden oder Wochen ohne sich Gedanken über Systemneustarts, Ausdauer und Nachrichtenintegrität umgehen konnte.

Ich habe nicht zu viel in sie aussehen, aber die Java 5+ Future Schnittstelle (oder dessen Unterschnittstellen) könnte für diese nützlich sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top