在Java中,我应该使用getter或接口标记来获取常量属性吗?

时间:2015-10-13 08:33:19

标签: java oop design-patterns interface

假设我正在用Java建模不同的动物。每只动物都有这些能力的组合:散步,游泳和飞翔。例如,能力集是不变的。

我可以将此信息存储为返回常量的getter。例如:

public class Penguin implements Animal {

    public boolean canWalk() {
        return true;
    }

    public boolean canSwim() {
        return true;
    }

    public boolean canFly() {
        return false;
    }

    // implementation... 
}

然后运行时检查:

if (animal.canFly()) {

    // Fly! 
}

或者我可以使用"标记"接口:

public class Penguin implements Animal, Flyer, Swimmer {

    // implementation... 
}

然后运行时检查:

if (animal instanceof Flyer) {

    // Fly! 
}

每种方法有哪些优缺点?

2 个答案:

答案 0 :(得分:5)

标记接口在现代Java中是一种反模式,在早期需要,因为无法直接向类添加元数据。 “现代”方法是注释:

read

运行时检查:

@Retention(RetentionPolicy.RUNTIME)
@interface Flyer {
}

@Retention(RetentionPolicy.RUNTIME)
@interface Swimmer {
}

@Flyer @Swimmer
public class Penguin implements Animal {
}

如果您想知道的是if(Animal.class.isAnnotationPresent(Flyer.class)) { // fly! } 是否具有此特征,那么您可以使用此方法,即航班和游泳功能是纯元数据。

你想要达到什么目的?我不会称之为OOP,因为OOP方法通常不是查询功能和执行特定于对象的条件逻辑,而是使用多态。

答案 1 :(得分:2)

步行/游泳/飞行能力与种类或状态有关吗?这是类标记(种类)和属性(状态)之间的真正区别。

你必须注意,一旦标记了一个类,就永远不能“无标记”。所有子类都将继承它。同样适用于单个实例,因为它无法动态更改其类型(至少在Java中)。

另一个评论与抽象有关。标记需要其他API来了解您的标记类型(接口,类或注释)。而某些API只需要依赖“抽象接口”(即方法名称)。 JavaBean-convention感知API就是这样的例子。并且比编写特定方法更容易集成,以检查类继承或注释存在。

总而言之,静态功能(如Runnable命令)可以依赖于类标记,其中动态的必须依赖于状态。