Heim  >  Artikel  >  Java  >  Detaillierte Erläuterung des Rückrufmechanismus von Java

Detaillierte Erläuterung des Rückrufmechanismus von Java

高洛峰
高洛峰Original
2017-01-24 11:52:351297Durchsuche

Es gibt immer eine bestimmte Schnittstelle zwischen Modulen. Aus Sicht der Aufrufmethoden können sie in drei Kategorien unterteilt werden: synchrone Aufrufe, Rückrufe und asynchrone Aufrufe. Im Folgenden wird der Rückrufmechanismus im Detail erläutert.

1. Übersicht

Der Rückrufmechanismus in Java ist ein relativ häufiger Mechanismus, in einigen großen Programmen kann er jedoch weniger verwendet werden überall im Framework zu finden. In diesem Artikel nähern wir uns anhand einiger spezifischer Beispiele langsam dem Rückrufmechanismus von Java.

2. Rückruf

Der sogenannte Rückruf: Klasse A ruft eine Methode C in Klasse B auf, und dann ruft Klasse B wiederum eine Methode in Klasse A auf. D, diese Methode D wird als Rückrufmethode bezeichnet. Bei der tatsächlichen Verwendung gibt es unterschiedliche Rückrufformen, wie zum Beispiel die folgenden.

2.1 Synchroner Rückruf

Hier gehe ich von einer solchen Situation aus.

Direktor B von Unternehmen A forderte seinen Untergebenen (Projektmanager C) auf, eine Umfrage durchzuführen, aber C musste dies nicht selbst tun. Sie können Manager C bitten, den ihm untergeordneten Programmierer D mit der Fertigstellung zu beauftragen. Manager C fand Programmierer D und teilte ihm mit, dass er nun eine Forschungsaufgabe erledigen müsse. Und teilen Sie Manager C die Ergebnisse der Umfrage mit. Wenn es Probleme gibt, müssen Sie trotzdem fortfahren. Denn hier fordert C D auf, etwas zu tun, und D muss dann noch das Ergebnis mit C kommunizieren. Dies ist das Rückrufmodell. Das Folgende ist ein Klassendiagramm eines allgemeinen Rückrufs:

Detaillierte Erläuterung des Rückrufmechanismus von Java

Zuerst benötigen wir eine Rückrufschnittstelle CallbackInterface

CallbackInterface.java

public interface CallbackInterface {
  public boolean check(int result);
}


Im Hintergrund möchte Programmierer D die Ergebnisse mit Projektmanager C kommunizieren, daher muss der Projektmanager hier die obige Rückrufschnittstelle implementieren:

Manager.java

public class Manager implements CallbackInterface {
 
  private Programmer programmer = null;
 
  public Manager(Programmer _programmer) {
    this.programmer = _programmer;
  }
 
  /**
   * 用于 Boss 下达的委托
   */
  public void entrust() {
    arrange();
  }
 
  // 进行安排下属进行 study 工作
  private void arrange() {
    System.out.println("Manager 正在为 Programmer 安排工作");
    programmer.study(Manager.this);
    System.out.println("为 Programmer 安排工作已经完成,Manager 做其他的事情去了。");
  }
 
  @Override
  public boolean check(int result) {
    if (result == 5) {
      return true;
    }
    return false;
  }
 
}


Für Programmierer D muss er einen Verweis auf Manager C halten die mit ihm kommunizieren. Dies ist jedoch eine Aufgabe, mit deren Organisation Direktor B Manager C beauftragt hat. D.h. es können hier auch andere Manager zugelassen werden, wie zum Beispiel die Manager B1, B2 usw. Da der Manager die Rückrufschnittstelle implementiert hat, kann Programmierer D diese Schnittstelle direkt halten. Wie folgt:

Programmer.java

public class Programmer {
 
  public void study(CallbackInterface callback) {
    int result = 0;
    do {
      result++;
      System.out.println("第 " + result + " 次研究的结果");
    } while (!callback.check(result));
 
    System.out.println("调研任务结束");
  }
}

Für den Regisseur ist es einfacher und klarer, da dies einem Client-Test entspricht:

Boss.java

public class Boss {
 
  public static void main(String[] args) {
    Manager manager = new Manager(new Programmer());
    manager.entrust();
  }
}

Laufendes Ergebnis:

Manager arrangiert Arbeit für Programmierer
Erste Studienergebnisse
Ergebnisse der 2. Studie
Ergebnisse der 3. Studie
Ergebnisse der 4. Studie
Ergebnisse der 5. Studie
Ende der Forschungsaufgabe
Arbeit für Programmierer arrangieren. Es wurde abgeschlossen und Der Manager hat andere Dinge erledigt.

2.2 Asynchroner Rückruf

Im obigen Beispiel kann Ihr Projektmanager jedoch nicht immer auf die Ergebnisse Ihrer Recherche warten. Aber nachdem er dir diese Aufgabe gegeben hat, wird er sich nicht darum kümmern. Er wird sein Ding machen und du wirst deins machen. Daher muss die Rückruffunktion asynchron verarbeitet werden.
Hier müssen wir also den Code der Programmer-Klasse wie folgt ändern:

Programmer.java

public class Programmer {
 
  public Programmer() {
  }
 
  public void study(CallbackInterface callback) {
    new StudyThread(callback).start();
  }
 
  // --------------------------- Programmer 正在做的工作 ---------------------------
 
  class StudyThread extends Thread {
 
    CallbackInterface callback = null;
 
    public StudyThread(CallbackInterface _callback) {
      callback = _callback;
    }
 
    @Override
    public void run() {
      int result = 0;
      do {
        result++;
        System.out.println("第 " + result + " 次研究的结果");
      } while (!callback.check(result));
 
      System.out.println("调研任务结束");
    }
  }
}

Betriebsergebnisse:

Manager arrangiert die Arbeit für den Programmierer
Die Organisation der Arbeit für den Programmierer ist abgeschlossen und der Manager ist gegangen, um andere Dinge zu erledigen.
Ergebnisse der 1. Studie
Ergebnisse der 2. Studie
Ergebnisse der 3. Studie
Ergebnisse der 4. Studie
Ergebnisse der 5. Studie
Forschungsaufgaben Ende

2.3 Abschlüsse und Rückrufe

Ein Abschluss ist ein aufrufbares Objekt, das einige Informationen aus dem Bereich aufzeichnet, in dem es erstellt wurde.

2.3.1 Normale Anrufe

Zuerst können wir uns ansehen, wie Anrufe unter normalen Umständen durchgeführt werden.
Incrementable.java

interface Incrementable {
  void increment();
}

Dies ist eine gemeinsame Schnittstelle (es ist nur eine gemeinsame Schnittstelle in einem normalen Aufruf und eine Rückrufschnittstelle in einem Rückruf. Dies sollte leicht verständlich sein).

Callee1.java

class Callee1 implements Incrementable {
 
  private int i = 0;
 
  @Override
  public void increment() {
    i++;
    System.out.println(i);
  }
 
}

Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();
    callee1.increment();
  }
}

Callbacks ist eine Test-Client-Klasse Es gibt nicht viel zu sagen, schauen Sie sich einfach den Code oben an.

2.3.2 Vorläufiger Test von Rückrufen

Zu den oben genannten gewöhnlichen Aufrufen gibt es nichts zu sagen, da dies für einen normalen Java-Programmierer etwas sein sollte, das ohne darüber nachzudenken durchgeführt werden kann . .

Wenn Sie nun einen Callback bilden möchten, ist es aufgrund der Programmstruktur oder des logischen Denkens unmöglich, nur einen Callee (das Callback-Objekt Callee1) zu haben. Sie benötigen auch ein Caller-Objekt. Der Anrufer kann wie folgt geschrieben werden:

Caller.java

class Caller {
 
  private Incrementable callbackReference;
 
  public Caller(Incrementable _callbackReference) {
    callbackReference = _callbackReference;
  }
 
  void go() {
    callbackReference.increment();
  }
}

Hier enthält Caller eine Callback-Schnittstellenreferenz callbackReference, Wie oben erwähnt, muss der Programmierer über eine Referenz zum Projektmanager verfügen, damit er über diese Referenz mit dem Projektmanager kommunizieren kann. Auch hier spielt die CallbackReference diese Rolle.

Jetzt werfen wir einen Blick auf das Schreiben der Testklasse:

Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();   
    Caller caller1 = new Caller(callee1);
    caller1.go();
  }
}

对于到目前为止的程序代码,完全可以对比上面项目经理安排程序员调研技术难题的代码。有异曲同工之妙。

2.3.3 闭包回调

相比于正常的回调,闭包回调的核心自然是在于闭包,也就是对作用域的控制。 
现在假设有一个用户(其他程序员)自定义了一个 MyInCrement 类,同时包含了一个 increment 的方法。如下:

class MyInCrement {
 
  public void increment() {
    System.out.println("MyCrement.increment");
  }
 
  static void f(MyInCrement increment) {
    increment.increment();
  }
}

另外有一个类 Callee2 继承自上面这个类:

class Callee2 extends MyInCrement {
 
  private int i = 0;
 
  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }
}

显而易见这里如果要调用 increment() 方法,就变成了一般的函数调用了。所以这里我们需要修改上面的 Callee2 类,修改的目标就是让 Callee2 类可以兼容 MyInCrement 类的 increment() 方法和 Incrementable 的 increment() 方法。修改后:

class Callee2 extends MyInCrement {
 
  private int i = 0;
 
  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }
 
  private class Closure implements Incrementable {
 
    @Override
    public void increment() {
      Callee2.this.increment();
    }
  }
 
  Incrementable getCallbackReference() {
    return new Closure();
  }
}

注意,这里的 Closure 类是一个私有的类,这是一个闭包的要素。因为 Closure 类是私有的,那么就要有一个对外开放的接口,用来对 Closure 对象的操作,这里就是上面的 getCallbackReference() 方法。 Caller 类则没有改变。 
对于测试客户端就直接看代码吧:

public class Callbacks {
  public static void main(String[] args) {   
    Callee2 callee2 = new Callee2();
    Caller caller2 = new Caller(callee2.getCallbackReference());
    caller2.go();
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多Detaillierte Erläuterung des Rückrufmechanismus von Java相关文章请关注PHP中文网!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn