如何在不使用instanceof的情况下查找类型?

时间:2011-09-17 07:42:31

标签: java instanceof

我的班级List中的Criteria接口类型为Query

List<Criteria> criteria = new ArrayList<Criteria>();

我有Criteria的几个具体实现。我想给Query一个迭代我criteria列表的方法,并根据具体类型执行一些逻辑。

我现在用instanceof这样做:

for(Criteria c : criteria) {
    if(c instanceof ContextualCriteria){
        // logic
    }
    ...
}

这是唯一/最好的方式吗?

7 个答案:

答案 0 :(得分:8)

逻辑是否合理地属于Criteria本身?如果是这样,请将其放入Criteria接口,并为实现Criteria接口的每个具体类适当地实现它。这显然是 nice 多态方法。

不幸的是,在现实生活中,OO并不总是像那样简单 - 有时将per-type行为放入类型本身是没有意义的,所以你可能需要使用instanceof代替。您可以潜在地拥有从“条件类”到某个界面的地图,代表要采取的行动,但这很容易变得更加混乱。

通过visitor pattern进行双重调度有时可以稍微改进一下 - 所以逻辑仍然可以在“调用”类中使用单独的方法,但每个Criteria可以通过单一接口方法将返回调用到正确的方法。就个人而言,我倾向于发现这种情况会增加耦合并迅速变得丑陋,但其他人则会发誓。

答案 1 :(得分:3)

如果Jon Skeet建议逻辑不属于Criteria,那么您可以使用visitor pattern

在ConcreteCriteria中:

public void accept(CriteriaVisitor v) {
    v.visit(this);
}

在客户端代码中:

public void method() {
    for (Criteria c : criteria) {
        c.accept(this);
    }
}

public void visit(ConcreteCriteria c) {
    // do logic here
}

public void visit(Criteria c) {
    // othervise...
}

这摆脱了实例,但要小心,我发现如果您不熟悉代码,这种模式很难理解。

答案 2 :(得分:1)

嗯,你可以......

if (ContextualCriteria.class.equals(c.getClass()) {

......虽然这只是一种看起来更像是instanceof的写作方式。 (好吧,差不多:这个测试它是否完全是类,而不是子类的类 - 对于你想要的isAssignableFrom())。

摆脱气味的正确方法是在Criteria中实现一个多态方法,例如在子类中重写。

答案 3 :(得分:1)

界面是策略模式的一半!要根据类型改变逻辑,请尽可能将其推送到接口后面,以便Criteria具有doLogic()。您可以传递该方法,无论您在调用代码中可能需要更改哪些参数,或者返回新信息 - 这些信息非常具体,很难从相关代码中获得建议。

如果一切顺利,您的主叫代码最终

for (Criteria c : criteria) {
    c.doLogic();
}

答案 4 :(得分:1)

您还可以在实现Criteria

的类中实现逻辑
public interface Criteria {
  public void logic();
}

在ContextualCriteria等类中有几个实现 你的循环看起来很干净:

for(Criteria c : criteria) {  
   c.logic();
}  

答案 5 :(得分:0)

您也可以使用:

for(Criteria c : criteria) {
   if(c.getClass() == ContextualCriteria.class){
       // logic
   }
   if ...
}

请注意Object#getClass()返回c的运行时类型,因此如果ContextualCriteria可以被子类化,则无法可靠地使用它。为此,您需要使用Class#isAssignableFrom()

for(Criteria c : criteria) {
   if(ContextualCriteria.class.isAssignableFrom(c)){
       // logic
   }
   if ...
}

答案 6 :(得分:0)

它没有任何问题。

从未使用instanceof的人只会写玩具应用程序。