标记接口还是布尔方法用于识别对象能力?

5
我正在开发一个较大的Java类层次结构,其中一些类具有我感兴趣的运行时查询属性(该属性仅适用于类,而不是特定实例)。
我可以创建一个抽象布尔方法isFooBar(),子类可以实现该方法以指示属性是否存在:
public abstract class MyBaseClass {
  ...
  public abstract boolean isFooBar();
}

或者我可以使用一个标记接口FooBarProperty并对接口进行instanceof检查:

public class MyConcreteClass extends MyBaseClass implements FooBarProperty {
   ...
}

或者你甚至可以像AmitD建议的那样使用注释:

@FooBarAnnotation
public class MyConcreteClass extends MyBaseClass {
   ...
}

每种方法的利弊是什么,通常应该选择哪种方法?

这段话的主要意思是在询问针对某种技术的不同方案所存在的优缺点,以及通常情况下应该选择哪种方案。

2
你可以在问题中添加另一个选项作为“注释”吗? - Amit Deshpande
1
我认为抽象方法在面向对象方面更清晰。使用 instanceof 经常是设计缺陷的标志。注解是类特定的 - 你可以将属性附加到类,但不能将其附加到实例。对于标记接口也是如此 - 你正在标记整个类,而不是单个实例。采用抽象方法的方法,每个对象都可以决定返回哪个值。 - Andreas Fester
我刚刚完成了重构的阅读,现在还保持着那种思维状态。我会选择第一种简单、代码量较少的选项。如果需要的话,我会选择第三种动态可扩展但需要更多编码的选项。 - Amit Deshpande
《框架设计指南》第二版,第99页及以下提出了两个观点(虽然是针对.NET的):1)检查注释比检查类型慢。2)使用接口,编译器可以强制实现标记的类。 - Stefan Hanke
2个回答

2

标记接口没有任何方法。在您的情况下,您的接口有一个获取属性的方法,基于此您应该使用接口。您可以简单地使用此接口来保存实现您的接口的类的具体实例,并调用与属性相关的方法。

然而,在另一端,标记被用于标记实例或层次结构,以便它将有资格获得某些功能,例如持久性。


2
标记接口在类层次结构中继承,因此它们的功能有限(您不能为某个特定子类“删除”此标记接口),我不建议使用它们(Cloneable是一个不好的例子)。问题是 - 您的属性是否真正绑定到对象的类,而不是实例?如果是这样,注释更好,因为它们不会向您的API添加附加方法,并且它们更易于维护 - 您只需添加/删除注释(在检查方法的情况下,您必须检查所有子类,无论它们是否覆盖它)。
编辑:在您的情况下,我会问自己一个问题:我的属性是否像“持久化”(适用于给定类的所有实例)还是“可见”(仅适用于某些实例)?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接