如何使用策略模式或函数式接口处理基于枚举值的多分支选择逻辑?
解决方案
核心思路
消除switch分支的本质是提前建立枚举值→对应处理逻辑的映射关系,运行时直接根据枚举值从映射中取出对应逻辑执行即可,不需要每次做分支判断,两种落地方式如下:
方案1:枚举结合Java函数式接口(轻量场景首选)
直接将验证逻辑绑定到枚举值上,代码改动最小,完全消除switch分支:
- 修改
CurrencyType枚举,新增函数式属性存储验证逻辑:
import java.util.function.Function; public enum CurrencyType { BTC(challenge -> { // 原verifyBTCMessage的实现逻辑直接写在这里 return challenge; }), ETH(challenge -> { // 原verifyETHMessage的实现逻辑直接写在这里 return challenge; }); // 函数式属性:入参Challenge,出参Challenge public final Function<Challenge, Challenge> verifier; CurrencyType(Function<Challenge, Challenge> verifier) { this.verifier = verifier; } }
- 修改
ChallengeService的verifyMessage方法,直接调用枚举绑定的验证逻辑:
@Service public class ChallengeService { public Challenge verifyMessage(final Challenge challenge) { return challenge.getCurrencyType().verifier.apply(challenge); } }
该方案适合验证逻辑简单、不需要依赖其他Spring Bean的场景,后续新增枚举值只要在枚举里新增对应逻辑即可,不需要修改服务代码。
方案2:Spring环境自动注册策略(复杂业务场景首选)
适合验证逻辑复杂、需要依赖其他Dao/Service等Bean的场景,完全符合开闭原则,后续新增币种不需要修改原有服务代码:
- 定义通用验证器接口:
public interface CurrencyVerifier { // 返回当前验证器对应的币种 CurrencyType getType(); // 验证逻辑 Challenge verify(Challenge challenge); }
- 每个币种单独实现验证器,添加
@Component注解交给Spring管理:
@Component public class BtcVerifier implements CurrencyVerifier { // 可以自由注入其他依赖,比如@Autowired private WalletDao walletDao; @Override public CurrencyType getType() { return CurrencyType.BTC; } @Override public Challenge verify(Challenge challenge) { // BTC验证逻辑 return challenge; } } @Component public class EthVerifier implements CurrencyVerifier { @Override public CurrencyType getType() { return CurrencyType.ETH; } @Override public Challenge verify(Challenge challenge) { // ETH验证逻辑 return challenge; } }
- 修改
ChallengeService,自动注入所有验证器并建立映射关系:
@Service public class ChallengeService { private final Map<CurrencyType, CurrencyVerifier> verifierMap; // Spring会自动把所有CurrencyVerifier的实现类注入到list中 public ChallengeService(List<CurrencyVerifier> verifiers) { verifierMap = new EnumMap<>(CurrencyType.class); verifiers.forEach(verifier -> verifierMap.put(verifier.getType(), verifier)); } public Challenge verifyMessage(final Challenge challenge) { CurrencyVerifier verifier = verifierMap.get(challenge.getCurrencyType()); if (verifier == null) { throw new IllegalStateException("Unexpected value: " + challenge.getCurrencyType()); } return verifier.verify(challenge); } }
后续新增币种只要新增对应的CurrencyVerifier实现类即可,不需要修改任何原有代码,完全避免了新增分支带来的维护问题。
方案对比
- 方案1:代码量少,无需额外接口和实现类,适合逻辑简单的工具类场景
- 方案2:解耦彻底,扩展性强,适合中大型业务系统使用
内容的提问来源于stack exchange,提问作者hc0re
相关产品推荐
相关产品推荐

