在做一个项目时,我被要求设计一组类来实现定义一个简单动作的接口。通常这些类会以特定的顺序一次性完成它们的工作,但仅从其中一个调用方法的可能性也是一个要求。
考虑到以上所有因素并考虑到: - 每个类都有相当基本的逻辑 - 不需要扩展另一个类 - 将所有类放在一个文件中可能很方便 - 在需要时编辑源文件不是问题
我想出了以下解决方案(实际课程并没有那么做作,但是下面的示例足以给您一些基本的想法):
public enum Bestiary {
DOG(1) {
@Override
void makeNoise(Loudspeaker ls) {
ls.shoutOutLoud("I am alpha dog");
}
},
CAT(2) {
@Override
void makeNoise(Loudspeaker ls) {
ls.shoutOutLoud("I am beta cat");
}
},
RAT(3) {
List<String> foods = new ArrayList<>();
{
foods.add("gods");
foods.add("dogs");
foods.add("cats");
foods.add("other rats");
}
@Override
void makeNoise(Loudspeaker ls) {
StringBuilder cry = new StringBuilder("I am THE rat; usually I eat ");
for (int i = 0; i < foods.size(); i++) {
cry.append(foods.get(i));
if (i != (foods.size() - 1)) {
cry.append(", ");
}
}
ls.shoutOutLoud(cry.toString());
}
},
THE_THING(4) {
String name = "r2d2";
@Override
void makeNoise(Loudspeaker ls) {
ls.shoutOutLoud(calculateHash(name));
}
private String calculateHash(String smth) {
return String.valueOf(smth.hashCode());
}
};
private int id;
public int getId() {
return id;
}
Bestiary(int id) {
this.id = id;
}
abstract void makeNoise(Loudspeaker ls); // all enum elements will need to implement this - kind of like implementing an interface (which was also an option); note that we pass some arbitrary object and call methods on it
}
调用此类的代码可能如下所示:
public final class Loudspeaker {
private static Loudspeaker loudspeaker = new Loudspeaker();
public static void shoutOutLoud(String cry) {
System.out.println(cry);
}
static class Noizemakers {
public static void makeSomeNoise() {
for (Bestiary creature: Bestiary.values()) {
System.out.println(creature + " with id " + creature.getId() + " says: ");
creature.makeNoise(loudspeaker);
}
}
}
public static void main(String[] args) {
Noizemakers.makeSomeNoise();
Bestiary.CAT.makeNoise(loudspeaker);
}
}
在代码审查期间,我的建议被嘲笑为“太老套,利用枚举具有类主体和方法的事实,并且总体上具有不好的代码气味”。虽然将它转换成一个单独的接口,一堆普通的 Java 类等只是几分钟的事情,但我对这个解释不太满意。是否有任何指导方针说您应该像其他语言一样仅以其基本形式使用枚举?这种方法有什么真正的缺点?Joshua Bloch 关于将单例编写为枚举的建议怎么样?在这种情况下,这样的枚举必须是一个成熟的类,对吧?