用接口+实现类+工厂模式替代if-else:工厂根据type返回统一接口的实例,主流程只调用handler.handle();避免在Service中new实现类或用反射,改用启动时扫描注解注册到Map,运行时查表并显式校验;无状态策略可单例,有状态需原型或工厂管理生命周期。

Java多态怎么替代if-else判断业务类型
直接说结论:用接口 + 实现类 + 工厂返回具体实例,把 if (type.equals("sms")) { ... } 这类分支逻辑彻底移出主流程。核心不是“用了多态”,而是把类型判断和行为绑定拆开——判断交给工厂,行为交给实现类。
常见错误是只抽一个 Handler 接口,但还在 Service 里写一长串 if-else 来 new 不同实现类,这根本没解决问题,只是把 if 搬了个地方。
- 真正有效的做法:让工厂根据
type字符串返回对应Handler实例,后续只调用handler.handle() - 所有实现类必须实现同一接口,且方法签名一致(不能一个带参数一个不带)
- 工厂内部可以用
Map<string handler></string>预注册,避免每次 if-else 或反射——反射慢、易错、难调试
策略模式里如何安全地从字符串获取策略实例
别用 Class.forName().newInstance(),JDK9+ 默认禁用,且构造失败抛 NoClassDefFoundError 而不是你预期的 IllegalArgumentException。
更稳的方式是提前注册 + 显式校验:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 启动时扫描所有
Handler实现类,按@HandlerType("email")注解或约定命名(如EmailHandler)存入Map - 运行时查
handlers.get(type),为空就明确抛UnsupportedOperationException("unknown handler type: " + type) - 避免在 get 时才加载类——类加载失败会打断整个流程,而注册阶段失败可立即暴露问题
工厂类要不要用 Spring 的 @Bean 管理策略实例
要看策略是否带状态。无状态(纯逻辑)可单例复用;有状态(比如含 ThreadLocal 或缓存字段)必须每次 new 或用原型作用域。
- Spring 默认单例,如果策略类里写了
private Map cache = new HashMap(),多个线程共用一个实例就会串数据 - 若用
@Scope("prototype"),注意 Spring 不会自动销毁原型 Bean,也不会调用@PreDestroy - 更轻量的做法:工厂自己管理实例生命周期,Spring 只管工厂本身,策略实例由工厂按需创建或复用
为什么 switch-case 比 if-else 好一点但依然不够好
switch (type) 在 JDK14+ 支持字符串且编译期优化成 hash 查找,性能略优,但本质仍是硬编码分支,新增类型就得改工厂或策略调度类,违反开闭原则。
- 加个新渠道(比如
"whatsapp"),你得改三处:加实现类、注册进工厂、可能还要改 enum 或常量类 - 而基于注解或配置文件驱动的工厂,只要加个新类 + 注解,其他地方完全不动
- 测试也更简单:每个
Handler可独立单元测试,不用 mock 整个 if-else 链
最易被忽略的是异常路径——当 type 传错、注册漏配、实现类抛未捕获异常时,主流程是否还能降级或记录日志。这些细节不在多态结构里,但在真实系统里决定能不能上线。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










