3

ビジターDPで両方acceptと機能が必要なのはなぜですか?visit典型的な例をとると:

class Visitor {
  visit(A a) { }
  visit(B b) { }
}

interface Element {
  accept(Visitor v);
}

class A implements Element {
  accept(Visitor v) {
    v.visit(this); // will call visit(A)
  }
}

class B implements Element {
  accept(Visitor v) {
    v.visit(this); // will call visit(B)
  }
}

ビジターDPを使用するには、のインスタンスとのインスタンスvがどこかにあり、次のようにします。VisitoreElement

e.visit(v)

単に呼び出す

v.visit(e)

では、なぜ2番目の呼び出しを実行して、メディエーター関数をバイパスできないのでしょうか。GoFは馬鹿ではないと思うので、何かが足りないと思います。それは何ですか?

4

2 に答える 2

3

これは、Visitorパターンの優れたリファレンスであり、次のように言及されています

プログラムでaccept()メソッドが呼び出されると、その実装は次の両方に基づいて選択されます。

  • 要素の動的タイプ。
  • 訪問者の静的タイプ。

関連するvisit()メソッドが呼び出されると、その実装は次の両方に基づいて選択されます。

  • 訪問者の動的タイプ。
  • accept()メソッドの実装内から認識される要素の静的タイプ。これは、要素の動的タイプと同じです。(ボーナスとして、訪問者が指定された要素の型の引数を処理できない場合、コンパイラーはエラーをキャッチします。)

したがって、visit()メソッドの実装は、次の両方に基づいて選択されます。

  • 要素の動的タイプ。
  • 訪問者の動的タイプ。

それから彼らは次のことに言及し続けます:

これにより、ダブルディスパッチが効果的に実装されます...

このように、要素のグラフをトラバースするための単一のアルゴリズムを記述でき、要素と訪問者。

これは、Java車の例で見ることができます。

class Car implements CarElement {
    CarElement[] elements;
    // ...
    public void accept(CarElementVisitor visitor) {     
        for(CarElement elem : elements) {
            elem.accept(visitor);
        }
        visitor.visit(this); 
    }
}

したがって、要約すると、あなたの例では、元のDP実装から多くのメリットを得ることができませんが、例がより複雑な場合、たとえば、 Elementのいくつかの内部実装を持つコンポジット(上記のJava車の例のように)、訪問者の行動をその内部要素の一部またはすべてに適用できます。

元の質問へのコメントに基づいて、このパターンには2つの部分があります。

  1. パターンの本来の動機は、オブジェクトの複雑な構造にアクセスし、アクセスするクラスインターフェイスを変更せずにオブジェクトに対して操作を実行することです。
  2. パターンの実装方法:これは、おっしゃるようにダブルディスパッチを使用した場合です。

次のデザインパターンブックを強くお勧めします。これは、多くの概念を実際に単純化するためです。GoFの本は時々あまりにも学術的です。

ヘッドファーストデザインパターン

この本によると、ビジターを使用することの長所と短所は次のとおりです。

(使用例のコンテキストで)

長所

  • 構造自体を変更せずに、複合構造に操作を追加できます
  • 新しい操作の追加は比較的簡単です
  • ビジターが実行する操作のコードは一元化されています

短所

  • 複合クラスのカプセル化は、Visitorが使用されると壊れます。
  • トラバーサル機能が関係しているため、複合構造への変更はより困難です
于 2012-07-30T13:31:04.717 に答える
0

その非常に単純な(しかしおそらく少し混乱する)、訪問者パターンの全体的なポイントは、訪問者を訪問されているものから切り離すことです。

accept()を使用すると、訪問者は特定のタイプの訪問者に公開する動作を選択できます。

ブレイディは同じことを言いました、私はそれをより少ない言葉で言いたかっただけです

于 2012-07-30T14:00:33.727 に答える