Java中如何优雅存储无逻辑规则的多枚举组合胜负判定结果
解决方案
方案1:枚举内置胜负规则(推荐,最符合开闭原则)
这种方案把每个枚举项的胜负规则绑定在自身定义里,新增枚举项时只需要补充当前项的胜负配置,完全不需要修改原有判断逻辑:
public enum Symbol { // 定义每个枚举项时,传入它能击败的所有枚举项 ROCK(Set.of(SCISSORS, LIZARD)), PAPER(Set.of(ROCK, SPOCK)), SCISSORS(Set.of(PAPER, LIZARD)), LIZARD(Set.of(PAPER, SPOCK)), SPOCK(Set.of(ROCK, SCISSORS)); // 存储当前枚举可以击败的所有Symbol集合 private final Set<Symbol> winAgainst; Symbol(Set<Symbol> winAgainst) { this.winAgainst = winAgainst; } public Result calculateResult(Symbol hand2) { if (this == hand2) { return Result.TIE; } return winAgainst.contains(hand2) ? Result.WIN : Result.LOSE; } } // 配套的Result枚举参考 public enum Result { WIN, TIE, LOSE }
方案优势:
- 新增枚举项时只需要在括号里配置它能赢的其他枚举即可,不需要修改任何分支逻辑
- 代码简洁无冗余,核心判断逻辑只有3行
- 规则和枚举项绑定,可读性高,看每个枚举的定义就能直接知道它的胜负关系
注意:原有代码里的
LOOSE是拼写错误,正确的失败语义应该用LOSE
方案2:集中式规则表(适合规则需要频繁调整的场景)
如果希望所有胜负规则统一管理,可以用二维枚举映射表存储所有判定逻辑:
public class RuleManager { private static final EnumMap<Symbol, EnumMap<Symbol, Result>> RULE_TABLE = new EnumMap<>(Symbol.class); static { // 初始化规则,只需要配置先手赢的场景,其余会自动补全 putRule(Symbol.ROCK, Symbol.SCISSORS, Result.WIN); putRule(Symbol.ROCK, Symbol.PAPER, Result.LOSE); putRule(Symbol.ROCK, Symbol.LIZARD, Result.WIN); putRule(Symbol.ROCK, Symbol.SPOCK, Result.LOSE); // 其余规则依次配置即可 } private static void putRule(Symbol hand1, Symbol hand2, Result result) { RULE_TABLE.computeIfAbsent(hand1, k -> new EnumMap<>(Symbol.class)).put(hand2, result); // 自动补全反向规则,减少配置量:hand1赢hand2等价于hand2输给hand1 RULE_TABLE.computeIfAbsent(hand2, k -> new EnumMap<>(Symbol.class)).put(hand1, result == Result.WIN ? Result.LOSE : result == Result.LOSE ? Result.WIN : Result.TIE); } public static Result getResult(Symbol hand1, Symbol hand2) { if (hand1 == hand2) { return Result.TIE; } return RULE_TABLE.get(hand1).get(hand2); } }
方案优势:
- 所有规则集中管理,不需要分散在各个枚举定义里
- 支持动态修改规则,不需要改动枚举定义
- 自动补全反向规则,配置量减少一半
内容的提问来源于stack exchange,提问作者Timo
相关产品推荐
相关产品推荐

