instanceof vs布尔类型检查

时间:2014-09-27 20:31:23

标签: java

我有一个名为Section和MapSection的接口,它扩展了section。我有一个Sections列表,如果它是MapSection,我需要做一些额外的处理。我可以通过两种方式处理这个问题。我可以在Section接口中添加一个布尔值isAMapSection()但是如果我添加更多类型,则会导致很多isA ..我能想到的另一种方式是检查实例,但我的OOP感觉认为这也不是很好。

curSection instanceof MapSection

其中一个是正确的方法?还是有另一种方式?

3 个答案:

答案 0 :(得分:4)

正如Oliver Charlesworth的评论所提到的那样,你可以使用Visitor Design Pattern来让代码根据所涉及的类型执行不同的操作,而不必使用一堆instanceof或class equals。

例如,假设您有两个类似的接口,Section和MapSection,其中grins将为MapSection提供一个额外的方法:

interface Section {
   void someMethod();
   void accept(SectionVisitor visitor);
}

interface MapSection extends Section {
   void additionalProcessingMethod();
}

我们还将给出Section accept(...)方法以允许类型为SectionVisitor的访问者采取行动,其界面如下:

interface SectionVisitor {
   void visit(Section section);
   void visit(MapSection mapSection);
}

visit方法将保存代码,该代码根据传入的类型知道调用哪些方法。

一个非常简单的具体示例可能如下所示:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class VisitorTest {
   public static void main(String[] args) {
      Random random = new Random();
      List<Section> sectionList = new ArrayList<>();
      for (int i = 0; i < 10; i++) {
         Section section = random.nextBoolean() ? new ConcreteSection() : new ConcreteMapSection();
         sectionList.add(section);
      }

      SectionVisitor visitor = new ConcreteSectionVisitor();
      for (Section section : sectionList) {
         section.accept(visitor);
      }
   }
}

interface Section {
   void someMethod();
   void accept(SectionVisitor visitor);
}

interface MapSection extends Section {
   void additionalProcessingMethod();
}

interface SectionVisitor {
   void visit(Section section);
   void visit(MapSection mapSection);
}

class ConcreteSection implements Section {

   @Override
   public void someMethod() {
      System.out.println("someMethod in ConcreteSection");
   }

   @Override
   public void accept(SectionVisitor visitor) {
      visitor.visit(this);
   }

}

class ConcreteMapSection implements MapSection {

   @Override
   public void someMethod() {
      System.out.println("someMethod in ConcreteMapSection");
   }

   @Override
   public void additionalProcessingMethod() {
      System.out.println("additionalProcessingMethod in ConcreteMapSection");
   }

   @Override
   public void accept(SectionVisitor visitor) {
      visitor.visit(this);
   }

}

class ConcreteSectionVisitor implements SectionVisitor {

   @Override
   public void visit(Section section) {
      section.someMethod();
   }

   @Override
   public void visit(MapSection mapSection) {
      mapSection.someMethod();
      mapSection.additionalProcessingMethod();
   }

}

答案 1 :(得分:3)

有时可以使用isXXX方法(并且相应的asXXX方法也很好),但这实际上取决于对象层次结构的开放性。

例如,在StAX中,XMLEvent接口将具有代表可以来自XML文档的不同类型事件的后代。但是这些类型的列表是封闭的(没有人会在短期内彻底改变XML格式)而且非常短(StAX API中有大约10种不同类型的事件),因此它是&#39;很好。这些接口还定义了其实现的主要特性,您不会像使用XMLEventSerializable一样用Iterable接口标记对象。

如果你的界面更多&#34;行为&#34; (因为缺少更好的词),更多可选(如Comparable)或过于开放(如LayoutManager),访问者或策略模式等内容可能更合适。

仅通过名称SectionMapSection判断,您的模型似乎属于第一类,但实际上只有您可以做出决定。我绝对不会做的是将代码的客户端留给instanceof调用。解决方案应该是Section的一部分。

答案 2 :(得分:2)

最好的办法可能是在Section中添加一个方法“additionalProcessing”。实现此方法以在MapSection中执行其他处理,并在其他实现中将其留空