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

时间:2014-09-16 16:07:59

标签: 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 new Coda();
  case "B" : return new Man();
 }

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

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

有没有java惯用的方法呢?

4 个答案:

答案 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模式时。首先考虑的好解决方案是否有任何阻止子类化的原因。