有人可以推荐一个java 8模式来替换switch语句吗?

jac*_*ack 8 java design-patterns java-8

我有以下代码:

 public class A {
    private String type;
    String getType() { return type;}
 }
Run Code Online (Sandbox Code Playgroud)

现在在许多代码处我都有这样的代码

 switch (a.geType()) {
  case "A" : return new Bla();
  case "B" : return new Cop();
 }
Run Code Online (Sandbox Code Playgroud)

或者别的地方

switch (a.geType()) {
  case "A" : return new Coda();
  case "B" : return new Man();
 }
Run Code Online (Sandbox Code Playgroud)

(请注意,我知道我应该在生产代码中使用Enumeration).

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

有没有java惯用的方法来做到这一点?

das*_*ght 13

当一个新类型被添加到class A编译器时应该标记所有switch需要调整的语句?

一个好的方法是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

有了这个基础设施,您可以删除您的switch语句,将其替换为访问者的实现:

Object res = a.accept(new VisitorOfA() {
    public Object visitA(A a) { return new Bla(); }
    public Object visitB(B b) { return new Cop(); }
});
Run Code Online (Sandbox Code Playgroud)

例如,当您添加新的子类型时A,class C您需要做的就是添加一个新方法VisitorOfA:

Object visitC(C c);
Run Code Online (Sandbox Code Playgroud)

现在,编译器将找到尚未实现此新方法的所有位置,从而帮助您避免运行时出现问题.


Stu*_*rks 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(); }
}
Run Code Online (Sandbox Code Playgroud)

如果要添加新的子类C,则需要提供抽象方法的实现(除非您使C本身成为抽象的).


ass*_*ias 6

你可以有一个字符串/供应商的地图:

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

您的示例代码将变为:

return map.get(a.getType()).get(); //need null check
Run Code Online (Sandbox Code Playgroud)