最简单的方法是使用 Java 的内置 instanceof 运算符。例如:
public boolean isAAA(Thing myThing)
{
return myThing instanceof AAA;
}
然而,许多人会告诉你,使用 instanceof 是糟糕的类设计的症状,而使用不同子类实现不同行为的正确方法是通过多态性。这里的问题是,在 Java 中很容易让一个类根据它是什么派生类型来做不同的事情,但是让一些其他对象根据它所具有的派生类型来不同地对待事物有点棘手。上。这就是双重调度问题。
如果在处理您的 Thing 对象时,您可以将问题分派给其他一些方法,这些方法将根据 Thing 的子类对它做不同的事情,那将是理想的,如下所示:
public void handleThing(Thing myThing)
{
reactToThing(myThing);
}
public void reactToThing(AAA myThing)
{
// Do stuff specific for AAA
}
public void reactToThing(BBB myThing)
{
// Do stuff specific for BBB
}
public void reactToThing(Thing myThing)
{
// Do stuff for generic Thing
}
然而,在仅支持单次调度的 Java 中,无论 handleThing() 中 myThing 的实际类型如何,reactToThing(Thing) 总是会被调用,并且您永远不会得到您的独特行为。
要解决这个问题,您需要做的是使用访问者模式。这只涉及在您的 Thing 类及其所有子类中添加一些额外的代码,以便为您的 reactToThing() 方法提供一些额外的上下文。因此,假设上述方法都在一个名为 Visitor 的类中。我们可以通过首先将问题交给 Thing 对象本身来重写上述内容,然后多态性将为我们提供适当的上下文(Thing、AAA 或 BBB),以便对象返回给访问者。
所以,我们可以将上面的例子改写如下:
public class Visitor
{
// ...
public void handleThing(Thing myThing)
{
myThing.accept(this);
}
public void reactToThing(AAA myThing)
{
// Do stuff specific for AAA
}
public void reactToThing(BBB myThing)
{
// Do stuff specific for BBB
}
public void reactToThing(Thing myThing)
{
// Do stuff for generic Thing
}
}
public class Thing
{
// ...
public void accept(Visitor visitor)
{
visitor.reactToThing(this);
}
}
public class AAA
{
// ...
public void accept(Visitor visitor)
{
visitor.reactToThing(this);
}
}
public class BBB
{
// ...
public void accept(Visitor visitor)
{
visitor.reactToThing(this);
}
}
那么为什么我需要在两个子类中重写相同的 accept() 方法呢?因为否则在调用visitor.reactToThing(this) 方法时,对象仍将处于Thing 上下文中,因此我们会遇到与以前相同的问题。通过在所有三个地方重新实现它,派生类将覆盖父类的实现,并在访问者中调用正确的方法。
当您只想知道正在使用的派生类时,这似乎需要做很多工作,但回报是可扩展性和维护性。现在您不需要到处添加 if (something instanceof somethingElse) 了。具体来说,如果您决定以后需要更改某些内容,例如扩展访问者,您需要维护的重复代码就会减少。
希望能解决你的问题。