有人能推荐Java8模式来代替switch语句吗?

有人能推荐Java8模式来代替switch语句吗?,java,design-patterns,java-8,Java,Design Patterns,Java 8,我有以下代码: 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

我有以下代码:

 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();
 }
(请注意,我知道应该在生产代码中使用枚举)

我想实现的是,当一个新类型被添加到类a中时,编译器应该标记所有需要调整的switch语句

有没有java惯用的方法来实现这一点

当一个新类型被添加到
类a
时,编译器应该标记所有需要调整的
开关
语句

解决这一问题的一个好方法是用更健壮的多分派实现替换
switch
语句,例如:

有了这个基础结构,您可以删除
开关
语句,用访问者的实现替换它们:

Object res = a.accept(new VisitorOfA() {
    public Object visitA(A a) { return new Bla(); }
    public Object visitB(B b) { return new Cop(); }
});
当您向
a
添加一个新的子类型时,比如说,
类C
,您所需要做的就是向
访问者a
添加一个新方法:

Object visitC(C c);

现在,编译器将发现所有未实现此新方法的地方,帮助您避免运行时出现问题。

您可以拥有字符串/供应商的地图:

Map<String, Supplier<Object>> map = new HAshMap<> ();
map.put("A", Bla::new);
map.put("B", Cop::new);

不要忘记好的老式多态性。在类中有一个带有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本身抽象化)。

从抽象的角度来看,还有另一种方法可供使用。一种方式是通过

一些简单的例子:

public void EverythingYouWant (Animal animal) {
    return animal.move();
}

当更多的是关于重构模式时。这是一个很好的解决方案,首先考虑是否有防止子类化的原因。 如果您使用枚举,我很确定java确实会标记不处理该条件的switch语句,只要该开关没有
默认值
条件。我只是尝试了一下。它不会将缺少的枚举标记出来,我这样做时会在eclipse中收到警告。不过,它可能不是java编译器本身的一部分。不知何故,switch语句看起来更轻量级,因此对于阅读代码的人来说更容易理解。但我必须承认,您的答案解决了“编译器标记”的要求。这种方法的一个很好的改进是将每个实现的一个实例存储到映射中。此外,您可以从.properties文件加载地图。@jack我同意,访问者模式对于第一次查看它的人来说看起来很棘手。我在这里有很大的偏见,因为我已经使用这种模式很多年了。然而,其优点是,人们只需要学习一次这种模式,就可以在将来可靠地识别它。这就像学习骑自行车一样:)访客模式对于预期会改变的类层次结构来说是一个糟糕的解决方案。GoF在第333页描述了访客的成本/收益。“当定义对象结构的类很少更改,但您通常希望在结构上定义新操作时,请使用访问者模式。更改对象结构类需要为所有访问者重新定义接口,这可能代价高昂。如果对象结构类经常更改,则最好定义e这些类中的操作。”
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(); }
}
public void EverythingYouWant (Animal animal) {
    return animal.move();
}