初级版本 先看一段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void trafficIfElseVersion (String trafficLight) { if ("红色" .equals(trafficLight)) { System.out.println("现在是红灯,请停下" ); } else if ("绿色" .equals(trafficLight)) { System.out.println("现在是绿灯,请通行" ); } else if ("黄灯" .equals(trafficLight)) { System.out.println("现在是黄灯,请注意" ); } } public void trafficSwitchVersion (String trafficLight) { switch (trafficLight) { case "红色" : System.out.println("现在是红灯,请停下" ); break ; case "绿色" : System.out.println("现在是绿灯,请通行" ); break ; case "黄色" : System.out.println("现在是黄灯,请注意" ); break ; default : break ; } }
上面两个版本有本质性区别吗?没有,对每个颜色的灯做一些响应,条件要写全
啰嗦进化 再来看一个版本
1 2 3 4 5 6 7 8 9 10 11 12 13 private static final Map<String, Consumer> TRAFFIC_LIGHT_TO_ACTION = new HashMap<>();static { TRAFFIC_LIGHT_TO_ACTION.put("红色" , o -> System.out.println("现在是红灯,请停下" )); TRAFFIC_LIGHT_TO_ACTION.put("绿色" , o -> System.out.println("现在是绿灯,请通行" )); TRAFFIC_LIGHT_TO_ACTION.put("黄色" , o -> System.out.println("现在是黄灯,请注意" )); } public static void trafficMapVersion (String trafficLight) { TRAFFIC_LIGHT_TO_ACTION.get(trafficLight).accept(null ); }
这个版本里简单动作(方法)可以这么搞,但还是要硬编码进去,而且对于 trafficLight 这样 String 类型,一直出现在代码中,属于魔法值,复杂的方法可以把各种灯抽象出来类,实例化后作为 value 添加进去
再进化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 import lombok.AllArgsConstructor;import lombok.Getter;import java.util.Arrays;import java.util.Map;import java.util.Optional;import java.util.stream.Collectors;@Getter @AllArgsConstructor public enum TrafficLight { RED("红灯" ) { @Override public void action () { System.out.println("现在是红灯,请停下" ); } }, GREEN("绿灯" ) { @Override public void action () { System.out.println("现在是绿灯,请通行" ); } }, YELLOW("黄灯" ) { @Override public void action () { System.out.println("现在是黄灯,请注意" ); } }; private String color; private static final Map<String, TrafficLight> COLOR_TO_ENUM = Arrays.stream(TrafficLight.values()) .collect(Collectors.toMap(TrafficLight::getColor, e -> e)); public static Optional<TrafficLight> getEnumByColorString (String color) { return Optional.ofNullable(COLOR_TO_ENUM.get(color)); } public abstract void action () ; public static void main (String[] args) { String color = "红色" ; Optional<TrafficLight> trafficLightOpt = getEnumByColorString(color); if (trafficLightOpt.isPresent()) { trafficLightOpt.get().action(); } } }
总结:
构建表 (MAP) 代替条件判断
抽象方法,多态调用具体实现
虽然代码没有少写,但是主逻辑确实清晰了许多,不同实例的不同实现封装到内部,清爽。
姊妹篇 枚举的常用姿势 (JAVA 为例)
枚举 & 表驱动的方式只适用于一些比较固定的情况,如果要结合 Spring 需要注入 service 和 dao 这种对象的时候,就不太合适了,这个时候该怎么办呢? 参见 Spring & 表驱动