Java取代switch_有⼈可以推荐⼀个java8模式来替换switch语
句吗?
我有以下代码:
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)。java网课推荐
我想要实现的是,当⼀个新类型添加到A类时,编译器应该标记所有需要调整的switch语句?
有没有java惯⽤的⽅法来做到这⼀点?
如果你使⽤枚举,我很确定java确实标记了不处理该条件的switch语句,只要该开关没有default条件。
我刚试了⼀下。 它不会标记缺少的枚举开头的枚举
我在⽇⾷时收到警告。 它可能不是java编译器本⾝的⼀部分。
when a new type is added to class A the compiler should flag all the switch statements that need to be adjusted?
⼀个很好的⽅法是使⽤更强⼤的多分派实现替换switch语句,例如访问者模式:
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);
现在,编译器将到尚未实现此新⽅法的所有位置,从⽽帮助您避免运⾏时出现问题。
不知何故,switch语句看起来更轻巧,因此对于阅读代码的⼈来说更容易理解。但我不得不承认你的答案解决了"编译器煽动"的要求
这种⽅法的⼀个很好的改进是将每个实现的实例存储到Map 中。此外,您可以从.properties⽂件加载地图。
@jack我同意,访客模式对于第⼀次看到它的⼈看起来很棘⼿。我在这⾥有很⼤的偏见,因为我多年来⼀直在使⽤这种模式。然⽽,优点是⼈们只需要学习⼀次这种模式,以便将来可靠地识别它。这就像学骑⾃⾏车:)
访问者模式对于预期会发⽣变化的类层次结构来说是⼀个糟糕的解决⽅案。 GoF描述了访客在第333页上的这种成本/收益。"当定义对象结构的类很少改变时,使⽤访问者模式,但是您经常要在结构上定义新操作。更改对象结构类需要将接⼝重新定义为所有访问者,这可能是昂贵的。如果对象结构类经常更改,那么在这些类中定义操作可能更好。"
不要忘记良好的⽼式多态性。在类中使⽤带有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本⾝成为抽象的)。
你可以有⼀个字符串/供应商的地图:
Map> map = new HAshMap<> ();
map.put("A", Bla::new);
map.put("B", Cop::new);
您的⽰例代码将变为:
(a.getType()).get(); //need null check
从抽象的⾓度来看,还有另⼀种⽅法可供您使⽤。⼀种⽅法是通过多态,如此处所⽰。
⼀些简单的例⼦:
public void EverythingYouWant (Animal animal) {
ve();
}
当它更多的是重构替换类型代码/检查状态/策略模式。这是⼀个很好的解决⽅案,⾸先考虑是否有任何原因阻⽌⼦类化。