2

このような訪問者がいるとしましょう

class Visitor : IVisitor
{
     void Accept(Visitable v)
     {
         /// other code
         v.AChild.Visit(this);
         v.BChild.Visit(this);
     }
}

AChild と BChild はまったく同じ型にすることができますが、訪問コードはそれらを区別する必要があります (AChild では BChild とは異なる動作をする必要があります)。これを行う最善の方法は何ですか?

  • 訪問者に状態を設定し、次の呼び出しでそれを確認します
  • 各子に異なる訪問者を渡す
  • 他の?

すみません、最初は逆にしました (現在Acceptは でしたVisit)。Wikipedia に示されているパターンと一致するようになりました。

すべての訪問方法は次のようになります。

void Visit(IVisitor v) { v.Accept(this); }
4

3 に答える 3

2

パターンが伝統的に使用されていると私が信じている方法から、あなたはまだメソッドに逆の名前を付けています。通常、Visitable(またはElement)にはacceptメソッドがあり、VisitorにはvisitXメソッドがあります。混乱を避けるために、従来の命名スキームを使用します:-)

IMOを機能させる最も簡単な方法は、Visitorインターフェースに、子のタイプごとに1つずつ、複数のメソッドを設定することです。子が同じ言語タイプであるかどうかは関係ありません。意味的に異なる場合は、異なるメソッドで処理する必要があります。

また、Visitableの構造に関する詳細でVisitor実装を汚染しないようにする必要があります。これを行うために、そのインターフェイスでchildAとchildBを公開する代わりに、acceptメソッドをVisitableインターフェイスに移動します。次に、Visitableの各実装は、訪問者のどのメソッドを各子に呼び出すかを決定できます。これにより、訪問者にすべての「場所」コンテキストが伝達され、優れた、クリーンな、分離されたソリューションが提供されます。

これが私が考えていることの例です。繰り返しになりますが、メソッド名を以前の名前に戻しました。

interface Visitable {
  accept(Visitor v)
}

interface Visitor {
  visitA(Node a)
  visitB(Node b)
}

class Container implements Visitable {
  private Node childA
  private Node childB

  ...
  void accept(Visitor v) {
    v.visitA(childA)
    v.visitB(childB)
  }
}

これで、2つの異なるメソッドを持つVisitorの実装ができました。1つはAの子を処理するためのもので、もう1つはBの子を処理するためのものです。

于 2009-02-09T22:41:45.090 に答える
0

元の投稿者による背景質問の回答から、次の追加情報が与えられます。

The visitor object is required to know the structure of the things it visits. That's OK, though. You're supposed to write specialized visit operations for each type of thing the visitor knows how to visit. This allows the visitor to decide how much it really wants to visit, and in what order.

私は答えます: おそらく ABChildVisitor と呼ばれる IVisitor の特別なクラスを作成します。

于 2009-02-09T22:39:58.963 に答える
0

アーキテクチャに基づいて、 を呼び出すだけv.Visit(this)で、 Visitable の実装で と の操作方法を決定できAChildますBChild

また、AChildandBChildはおそらく Visitable のインスタンスのプライベート メンバーであるべきだと考えてください。

于 2009-02-09T22:10:29.953 に答える