0

Java などの複数のディスパッチをサポートしていない言語では、コードはおそらく次のようになります。

/* Example using run time type comparison via Java's "instanceof" operator */
interface Collideable {
  void collideWith(Collideable other);
}

class Asteroid implements Collideable {
 public void collideWith(Collideable other) {
     if (other instanceof Asteroid) {
        System.out.println("AAAAAA");
     } else if (other instanceof Spaceship) {
        System.out.println("BBBBBB");
     } else if (other instanceof Plane) {
        System.out.println("CCCCCCC");
     } 
 }
}
class Spaceship implements Collideable {
 public void collideWith(Collideable other) {
     if (other instanceof Asteroid) {
         System.out.println("DDDDDDD");
     } else if (other instanceof Spaceship) {
         System.out.println("EEEEEEE");
     } else if (other instanceof Plane) {
        System.out.println("FFFFFFF");
     } 
 }
}
class Plane implements Collideable {
 public void collideWith(Collideable other) {
     if (other instanceof Asteroid) {
       System.out.println("GGGGGGG");
     }else if (other instanceof Spaceship) {
       System.out.println("HHHHHHH");
     }else if (other instanceof  Plane) {
       System.out.println("KKKKKK");
     }
 }
}

ビジター パターンはこの問題の解決に役立つので、各リーフ クラスに void collideWith() { visitor.visit(this); を実装する必要があるかどうかを考えています。// 訪問者はセッターで設定されます }

interface Visitor {
   void visit(Collideable c);
   void visit(Asteroid c);
   void visit(Spaceship c);
   void visit(Plane c);
}

次に、それぞれの一意の println を次のようにビジターのサブクラスに実装する必要がありますか?

class AsteroidVisitor implements Visitor {
   void visit(Collideable c) {}
   void visit(Asteroid c) { System.out.println("AAAAAA"); }
   void visit(Spaceship c) { System.out.println("BBBBBBB"); }
   void visit(Plane c) { System.out.println("CCCCCC"); }
}
//etc for SpaceshipVisitor and PlaneVisitor()

この種のリファクタリングに対処して instanceof を置き換えるのが最善の方法ですか?

編集: 印刷は、各メソッドの固有の操作の例にすぎず、最終的な結果ではありません。明確にするために例を変更します。

4

3 に答える 3

1

あなたが示した例では、2 つのインターフェイスは必要ありませんCollideable。インターフェイスだけが必要です。Collideable インターフェースは次のように定義できます。

interface Collideable {
  void collideWith(Collideable other);
  String getType();
}

次に、、、SpaceshipおよびPlaneすべてAsteroidが実装さcollideWithgetTypeます。実装例として、Spaceship の実装は次のようになります。

class Spaceship implements Collideable {
 public void collideWith(Collideable other) {
     System.out.println(this.getType() + " collides with " + other.getType());
 }

 public String getType(){
   return "Spaceship";
 }
}

さらに一歩進んで、Collideable を抽象クラスとして宣言し、常に同じであるため、collideWith の実装を提供できます。例えば:

abstract class Collideable {
  void collideWith(Collideable other){
    System.out.println(this.getType() + " collides with " + other.getType());
  }
  String getType();
}

補足として、一般的なヒントとして、あなたのVisitorインターフェースは貧弱なデザインです。インターフェイスの目的は、そのインターフェイスを実装するすべてのクラスがメソッド定義 (実装) を提供する必要があるメソッドを定義することです。ただし、インターフェイスは非常に具体的です。メソッド パラメーターとしていくつかの型 ( 、 など) を提供しSpaceshipますAsteroid。したがって、それは悪い設計です。そもそもなぜそのインターフェイスが必要だったのですか? 他では使えないようです。

于 2013-04-19T20:31:38.233 に答える