我有以下代码:
public class A {
private String type;
String getType() { return type;}
}
现在在许多代码处我都有这样的代码
switch (a.geType()) {
case "A" : return new Bla();
case "B" : return new Cop();
}
或其他地方
switch (a.geType()) {
case "A" : return new Coda();
case "B" : return new Man();
}
(请注意,我知道我应该在生产代码中使用Enumeration)。
我想要实现的是,当一个新类型被添加到A类时,编译器应该标记所有需要调整的switch语句?
有没有java惯用的方法呢?
答案 0 :(得分:13)
当一个新类型被添加到
class A
时,编译器应该标记所有需要调整的switch
语句?
一个好方法是用{em>多个调度更强大的实现替换switch
语句,例如Visitor Pattern:
interface VisitorOfA {
Object visitA(A a);
Object visitB(B b);
}
class A {
Object accept(VisitorOfA visitor) {
return visitor.visitA(this);
}
}
class B extends A {
Object accept(VisitorOfA visitor) {
return visitor.visitB(this);
}
}
有了这个基础架构,您可以删除switch
语句,将其替换为访问者的实现:
Object res = a.accept(new VisitorOfA() {
public Object visitA(A a) { return new Bla(); }
public Object visitB(B b) { return new Cop(); }
});
当您向A
添加新的子类型时,例如class C
,您需要做的就是向VisitorOfA
添加新方法:
Object visitC(C c);
现在,编译器将找到尚未实现此新方法的所有位置,帮助您避免运行时出现问题。
答案 1 :(得分:8)
不要忘记良好的老式多态性。在类中使用带有switch语句的“type”字段通常是一种气味,表明子类化可能很有用。考虑:
public abstract class CommonSuperClass {
public abstract One getOne();
public abstract Two getTwo();
}
public class A extends CommonSuperClass {
@Override public One getOne() { return new Bla(); }
@Override public Two getTwo() { return new Coda(); }
}
public class B extends CommonSuperClass {
@Override public One getOne() { return new Cop(); }
@Override public Two getTwo() { return new Man(); }
}
如果你要添加一个新的子类C,你需要提供抽象方法的实现(除非你让C本身是抽象的)。
答案 2 :(得分:3)
您可以拥有字符串/供应商的地图:
Map<String, Supplier<Object>> map = new HAshMap<> ();
map.put("A", Bla::new);
map.put("B", Cop::new);
您的示例代码将变为:
return map.get(a.getType()).get(); //need null check
答案 3 :(得分:0)
从抽象的角度来看,您可以使用另一种方法。一种方法是通过Polymorphism as shown here。
一些简单的例子:
public void EverythingYouWant (Animal animal) {
return animal.move();
}
当它更多地关于重构 replace type code/checking with State/Strategy模式时。首先考虑的好解决方案是否有任何阻止子类化的原因。