18

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);
    }
}

コールバックですか、それともデリゲートですか (デリゲートとコールバックは同じですか、または類似していますか? )。

次に別のものを実装する方法は?

4

3 に答える 3

37

これはコールバックです。ウィキペディアによると

コンピューター プログラミングでは、コールバックは、他のコードに引数として渡される実行可能コードへの参照です。

それでは、実行可能コードを見てみましょう。

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

ここで、callback引数は type のオブジェクトへの参照HelpCallbackです。その参照は引数として渡されるため、コールバックです。

委任の例

委任は、メソッドがどのように呼び出されるかに関係なく、オブジェクトによって内部的に行われます。たとえば、callback変数が引数ではなくインスタンス変数の場合:

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();
    }
}

...それなら委任です。

ここでMyObjectは、戦略パターンを使用します。注意すべき点が 2 つあります。

  1. の呼び出しにgetHelp()は、実行可能コードへの参照を渡す必要はありません。つまり、これはコールバックではありません。
  2. MyObject.getHelp()呼び出すという事実は、オブジェクトhelpStrategy.getHelp()のパブリック インターフェイスまたは呼び出しからは明らかではありません。この種の情報隠蔽は、委任の特徴です。MyObjectgetHelp()

また、メソッドに// do somethingセクションがないことにも注意してください。getHelp()コールバックを使用する場合、コールバックはオブジェクトの動作に関連することは何もしません。何らかの方法で呼び出し元に通知するだけなので、// do somethingセクションが必要でした。ただし、委任を使用する場合、メソッドの実際の動作は委任に依存します。したがって、実際には両方が必要になる可能性があります。これらは異なる目的を果たすためです。

    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
        }
    }
于 2012-09-29T18:12:04.050 に答える
6

「コールバック」は、呼び出しているモジュールに、そのモジュールがコードを呼び出す方法を提供する一般的なパターンの名前であると主張します。AC# デリゲート、または ObjC デリゲート オブジェクト (これら 2 つはまったく別のものです) または Java クラス実装コールバック インターフェイスは、コールバック パターンを実装するプラットフォーム固有の異なる方法です。(それら自体をパターンと見なすこともできます。) 他の言語では、多かれ少なかれ微妙に異なる方法があります。

上記の「デリゲート」の概念は、デリゲートを 1 つと考えることができる戦略パターンにも似ています。同様に、訪問者もコールバックの一種です。(訪問者は、訪問した各アイテムを処理するための戦略でもあります。)

「コールバック」も「デリゲート」も正式な用語ではなく、あなたの環境で有効な以前の定義を参照せずにそれらについて議論することはほとんど意味がないため、これはすべて私にとって直感的な定義を使用しており、他の人にとってはそうではない可能性があります。環境。したがって、定義が何であるかを尋ねることはほとんど意味がありません。私の知る限りでは、信頼できるものはないからです。つまり、この質問に対する他の回答は、まったく異なることを言っている可能性が高いという事実です。

私が推奨するのは、セマンティクスの詳細ではなく、設計のメリット (必要なものを実現するかどうか、密結合を導入しないかどうかなど) に焦点を当てることです。2 つの設計パターンが似ている場合、それらを使用して同様の目標を同等に達成できる可能性があります。

于 2012-09-29T17:58:17.257 に答える
1

達成したいのは、サービスがクライアントに依存することを回避しながら、元の呼び出し元とサービスの間の双方向通信です。その目的のために使用するパターンは、多くの場合、言語の制限によって異なります。関数ポインター、クロージャー、またはこれらのいずれも使用しない場合は、コールバック オブジェクト (クロージャーと見なされる場合もあります) を使用します。

また、同じパターンまたは非常に類似したパターンに対して、多くの異なる名前が付けられることがよくあります。

于 2012-09-29T17:58:45.057 に答える