我有一个名为Section和MapSection的接口,它扩展了section。我有一个Sections列表,如果它是MapSection,我需要做一些额外的处理。我可以通过两种方式处理这个问题。我可以在Section接口中添加一个布尔值isAMapSection()但是如果我添加更多类型,则会导致很多isA ..我能想到的另一种方式是检查实例,但我的OOP感觉认为这也不是很好。
curSection instanceof MapSection
其中一个是正确的方法?还是有另一种方式?
答案 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;很好。这些接口还定义了其实现的主要特性,您不会像使用XMLEvent
或Serializable
一样用Iterable
接口标记对象。
如果你的界面更多&#34;行为&#34; (因为缺少更好的词),更多可选(如Comparable
)或过于开放(如LayoutManager
),访问者或策略模式等内容可能更合适。
仅通过名称Section
和MapSection
判断,您的模型似乎属于第一类,但实际上只有您可以做出决定。我绝对不会做的是将代码的客户端留给instanceof
调用。解决方案应该是Section
的一部分。
答案 2 :(得分:2)
最好的办法可能是在Section中添加一个方法“additionalProcessing”。实现此方法以在MapSection中执行其他处理,并在其他实现中将其留空