在不支持多个调度的语言中,例如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(本); //访问者在setter中设置 }
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的最佳方法吗?
编辑:打印输出只是每种方法中唯一操作的一个例子,而不是最终结果。我修改我的例子是清楚的。
答案 0 :(得分:1)
在您给出的示例中,您不需要两个接口,只需要Collideable
接口。 Collideable接口可以定义如下:
interface Collideable {
void collideWith(Collideable other);
String getType();
}
然后Spaceship
,Plane
和Asteroid
都会实施collideWith
和getType
。作为一个示例实现,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
等)作为方法参数。因此它是糟糕的设计,为什么你甚至需要开始接口?看起来它不能在其他任何地方使用。
答案 1 :(得分:0)
双重调度与方法重载有关。您在代码片段中显示的内容仅依赖于单个调度 - 您有一个接口,其实现将在运行时调用。
正如我所看到的,真正的问题是你的Collidable
界面应该有getName
或getType
方法,它会返回“小行星”或“宇宙飞船”或者你有什么,然后你的collidesWith
的实现可以简单地打印出自己的名字和碰撞伙伴的名字。我在这个例子中没有看到你需要双重发送 - 只是为什么instanceof
是代码气味的情况。
答案 2 :(得分:0)
我希望我理解你的问题。
您可以考虑添加一个方法,例如:
interface Collideable {
void collideWith(Collideable other);
//new method
String getSpecificStuff();
}
class Asteroid implements Collideable {
String getSpecificStuff(){
return "Asteroid";
}
}
然后方法:
public void collideWith(Collideable other) {
System.out.println(this.getSpecificStuff() +" VS " + other.getSpecificStuff());
}
其他子类只遵循上述规则。
当然,这些仅仅是一些例子。您可以使用真实逻辑实现自己的getSpecificStuff()
方法。
代码不是用IDE编写的,如果有错字或眼睛伤害的格式,我会很抱歉。