2

私はVisitor Patternをよくマスターします。しかし、私は何か疑問に思っています。

ビジター パターンを使用する最も重要な動機は、実際のデータ オブジェクト タイプをチェックする必要なく、クライアント側で特定のデータ モデルを含むロジックを追加することです。解決に使用される手法は、Double-Dispatching と呼ばれます。

したがって、accept()メソッドを実装するデータ モデルのコード スニペットは次のとおりです。

public class Ferrari extends Car {
    //......
    @Override
    public void accept(Visitor v){
      v.visit(this);
    }
  }

そしてここにPrintCarVisitor実装Visitorインターフェースがあります:

public class PrintCarVisitor implements Visitor {
  //...
  @Override
  public void visit(Ferrari c){
    System.out.println("Ferrari");
  }
}

したがって、if/elseシリーズとinstanceofシリーズは必要ありません。

すべてのクライアントは次のようになります。

Visitor visitor = new PrintCarVisitor();
car.accept(visitor);  //no need to know the exact Car's type

しかし、Visitor は Open/Closed Principle を保持していないため (新しいデータ モデルが独自のvisitメソッドを追加することでクラスを破壊するため)、なぜわざわざ二重ディスパッチを行うのでしょうか?

if/elseビジターの実装内でシリーズを分離することはできませんか。

この仮想的な代替案を使用すると、コードのこの部分が消えます。

 public class Ferrari extends Car {
    //This method is not needed anymore with this alternative
    @Override
    public void accept(Visitor v){
      v.visit(this);
    }
  }

PrintCarVisitorだろう:

public class PrintCarVisitor {
   public void visit(Car c){
     if(c instanceof Ferrari){
       System.out.println("Ferrari");
     }
   }      
}

この代替手段を使用しても、すべての呼び出し元は、次のようにデータ モデルの抽象化を処理します。

new PrintCarVisitor().visit(car); //no need to know the exact data type in client side

アプリオリに、この 2 番目のアプローチは、純粋な Visitor パターンの実装中に生成されるすべてのボイラープレートを必要としないため、優れています。

このアプローチには 2 つの欠点があると思います。

1)Visitor使用されたビジターがCar現在処理されているメソッドに対応するメソッドを破棄するという保証はありません (インターフェイスが課すように)。

2) BoilerPlate コードは、一連のinstanceofおよびを使用して、Visitor 実装クラスにより重いままcastingです。

Visitor Pattern が Double Dispatching を使用する必要がありinstanceof、クラス内でシリーズを単純に分離できない理由を説明する他の欠点はありますか (Factoryたとえば、静的なように)?

4

2 に答える 2

4
  1. これを行うと、ビジターはなくなります。基本的には、ある種のプロセッサーを使用します。あなたのコードは、ループを通過するたびに、以前acceptはビジターだったプロセッサに以前使用していたものを渡すリストの繰り返しになります。訪問者が訪問者を訪問する代わりに、ある意味でパラダイムを逆転させます。訪問者は最初にワーカーに渡されるため、訪問者になります。あなたならできます。ただし、それをビジターとは呼びません。

  2. 従来の通念では、通常、 の使用はinstanceof最後の手段として予約する必要があります。Java のポリモーフィズムに任せることができるのに、なぜ を使用するinstanceofのでしょうか? オブジェクトを持つことのポイントの 1 つは、この利点です。これを行う場合instanceof、メソッドのオーバーライドの場合、動的ディスパッチに頼るのではなく、メソッドのオーバーライドを避けて、クラスのメソッドで何をすべきかを決定するために使用してみませんか?

于 2012-12-17T13:16:01.450 に答える
1

Xtext プロジェクトにも同じ問題があり、ヘルパー クラスを作成しましたPolymorphicDispatcher。簡単に言えば、PolymorphicDispatcherコンパイル時にコンパイラが行うことを実行時に行います。一連のパラメータに最もよく一致するメソッドを見つけて、それを呼び出します。

したがって、訪問者は次のようになります。

 public class PrintCarVisitor {
   public void visit(Car c){
      System.out.println("Just a car");
   }
   public void visit(Ferrari c){
      System.out.println("A Ferrari!");
   }
 }

これがソースです。

于 2012-12-17T13:17:17.310 に答える