it-swarm.com.de

Delegate vs Callback in Java

Ich habe einige Missverständnisse über Begriffe von Delegierten und Rückrufen in Java.

class MyDriver {

    public static void main(String[] argv){
        MyObject myObj = new MyObject();
        // definition of HelpCallback omitted for brevity
        myObj.getHelp(new HelpCallback () {
            @Override
            public void call(int result) {
                System.out.println("Help Callback: "+result);
            }
        });
    }
}

class MyObject {

    public void getHelp(HelpCallback callback){
        //do something
        callback.call(OK);
    }
}

Handelt es sich um einen Rückruf oder um einen Delegierten ( Sind Delegierten und Rückrufe gleich oder ähnlich? )?

Wie setzt man dann noch einen um?

16
pvllnspk

Dies ist ein Rückruf. Laut Wikipedia :

In der Computerprogrammierung ist ein Rückruf ein Verweis auf einen ausführbaren Code, der als Argument an einen anderen Code übergeben wird.

Schauen wir uns also den ausführbaren Code an:

public void getHelp(HelpCallback callback){
    //do something
    callback.call(OK);
}

Hier ist das Argument callback eine Referenz auf ein Objekt vom Typ HelpCallback. Da diese Referenz als Argument übergeben wird, handelt es sich um einen Rückruf.

Ein Beispiel für eine Delegation

Die Delegierung erfolgt intern durch das Objekt - unabhängig davon, wie die Methode aufgerufen wird. Wenn zum Beispiel die Variable callback kein Argument, sondern eine Instanzvariable ist:

class MyDriver {

    public static void main(String[] argv){
        // definition of HelpStrategy omitted for brevity
        MyObject myObj = new MyObject(new HelpStrategy() {
            @Override
            public void getHelp() {
                System.out.println("Getting help!");
            }
        });
        myObj.getHelp();
    }

}

class MyObject {
    private final HelpStrategy helpStrategy;

    public MyObject(HelpStrategy helpStrategy) {
        this.helpStrategy = helpStrategy;
    }

    public void getHelp(){
        helpStrategy.getHelp();
    }
}

... dann wäre es Delegation.

Hier verwendet MyObject das Strategiemuster . Es gibt zwei Dinge zu beachten:

  1. Beim Aufruf von getHelp() wird kein Verweis auf ausführbaren Code übergeben. das ist kein Rückruf.
  2. Die Tatsache, dass MyObject.getHelp()helpStrategy.getHelp() aufruft, ergibt sich nicht aus der öffentlichen Schnittstelle des Objekts MyObject oder aus dem Aufruf getHelp(). Diese Art des Versteckens von Informationen ist etwas charakteristisch für die Delegation.

Bemerkenswert ist auch das Fehlen eines // do something-Abschnitts in der getHelp()-Methode. Bei Verwendung eines Rückrufs hat der Rückruf keine Auswirkungen auf das Verhalten des Objekts: Er benachrichtigt den Anrufer lediglich auf irgendeine Weise, weshalb ein Abschnitt // do something erforderlich war. Wenn Sie jedoch die Delegierung verwenden, hängt das tatsächliche Verhalten der Methode vom Delegierten ab. Wir könnten also letztendlich beide benötigen, da sie unterschiedlichen Zwecken dienen:

    public void getHelp(HelpCallback callback){
        helpStrategy.getHelp(); // perform logic / behavior; "do something" as some might say
        if(callback != null) {
            callback.call(); // invoke the callback, to notify the caller of something
        }
    }
34

Ich würde argumentieren, dass "Rückruf" ein Name für ein generisches Muster ist, bei dem Sie dem Modul, das Sie aufrufen, eine Möglichkeit geben, mit der das Modul Ihren Code aufrufen kann. Ein C # -Delegierter oder ein ObjC -Delegierter-Objekt (diese beiden sind völlig verschiedene Bestien) oder eine Java-Klasse, die die Callback-Schnittstelle implementiert, sind unterschiedliche, plattformspezifische Methoden zum Implementieren des Callback-Musters. (Sie können auch selbst als Muster betrachtet werden.) Andere Sprachen haben mehr oder weniger unterschiedliche Möglichkeiten, dies zu tun.

Das obige Konzept des "Delegierten" ähnelt auch dem Strategiemuster, bei dem der Delegierte als einer betrachtet werden kann. Ebenso ist ein Besucher auch eine Art Rückruf. (Ein Besucher ist auch eine Strategie für die Verarbeitung jedes besuchten Elements.)

All dies verwendet Definitionen, die für mich intuitiv sind und für andere möglicherweise nicht gelten, da weder "Rückruf" noch "Delegierter" formale Begriffe sind und es wenig sinnvoll ist, sie zu diskutieren, ohne auf eine vorherige Definition davon zu verweisen, die für Sie gültig ist Kontext. Daher ist es wenig sinnvoll, nach der Definition zu fragen, da es meines Wissens keine maßgebliche gibt. Die Tatsache, dass andere Antworten auf diese Frage wahrscheinlich etwas ganz anderes aussagen.

Meine Empfehlung wäre, sich auf die Vorzüge Ihres Designs zu konzentrieren - ob es das erreicht, was Sie benötigen, keine enge Kopplung einführt usw. - anstatt auf die Semantik-Minutien. Wenn zwei Entwurfsmuster ähnlich aussehen, können sie wahrscheinlich verwendet werden, um ähnliche Ziele gleich gut zu erreichen.

5
millimoose

Was Sie erreichen möchten, ist eine bidirektionale Kommunikation zwischen dem ursprünglichen Anrufer und einem Dienst, wobei vermieden wird, dass der Dienst vom Kunden abhängt. Das Muster, das Sie für dieses Ziel verwenden, hängt häufig von den Einschränkungen Ihrer Sprache ab. Sie verwenden Funktionszeiger, Abschlüsse oder, falls Sie keines dieser Objekte haben, Callback-Objekte (die auch als Abschlüsse angesehen werden können).

Und dann gibt es oft viele verschiedene Namen für dasselbe oder ein sehr ähnliches Muster.

1
nansen