用多态和抽象类替代硬编码条件控制流,核心是将类型/状态分支从主流程抽离,通过策略接口、模板方法和自动注册表实现开闭原则,使业务代码只依赖接口、不感知具体类型。

用多态和抽象类替代硬编码条件控制流,核心是把“根据类型/状态做不同处理”这个变化点从主流程中抽离出来,让运行时决定行为,而不是编译期写死分支。
把 if-else 或 switch 提炼成策略接口
原始代码里常见这样的逻辑:
if ("discount_vip".equals(type)) { applyVipDiscount(); }
else if ("discount_holiday".equals(type)) { applyHolidayDiscount(); }
else if ("discount_bulk".equals(type)) { applyBulkDiscount(); }
这种写法导致每加一种折扣类型就要改业务类,违反开闭原则。重构做法是:
- 定义统一接口 DiscountStrategy,声明 calculate(Order order) 方法
- 为每种折扣实现独立类:VipDiscountStrategy、HolidayDiscountStrategy、BulkDiscountStrategy
- 业务类只依赖 DiscountStrategy 接口,通过构造器注入或工厂获取实例
- 调用方只需写 strategy.calculate(order),完全不关心背后是谁
用抽象类封装共性流程,把差异点下沉为钩子方法
很多业务流程骨架一致(比如“校验→计算→记录→返回”),只是中间某步逻辑不同。这时适合用模板方法模式:
定义抽象类 AbstractOrderProcessor:
- final Object process(Order order):固定执行顺序,不可重写
- abstract boolean validate(Order order):由子类实现校验规则
- abstract BigDecimal computeAmount(Order order):由子类实现金额计算逻辑
- abstract void logResult(Order order, BigDecimal result):由子类决定怎么记日志
每个具体处理器(如 VipOrderProcessor、OverseasOrderProcessor)只专注自己那块差异,主流程复用、无重复、易测试。
让类型选择脱离代码,交给配置或注册表
避免在工厂里写一堆 if-else 来选策略。正确方式是启动时自动注册:
- 所有 DiscountStrategy 实现类标注 @Supports("vip") 注解
- 系统扫描这些类,构建 Map
注册表 - 工厂的 getStrategy(String type) 方法只查表:registry.get(type.toLowerCase().trim())
- 新增折扣类型?加个类 + 注解即可,业务和工厂代码都不动
警惕多态没真正生效的信号
如果出现以下情况,说明重构没到位,条件逻辑依然隐性存在:
- 业务代码里有 instanceof 判断或强制转型
- 调用前先写 if (strategy instanceof VipDiscountStrategy)
- 工厂被 new 在 Service 里,而不是通过 DI 容器注入
- 配置项传的是类全名(如 "com.xxx.VipDiscountStrategy"),而不是语义标识(如 "vip")
真正的多态落地,是业务层看不见任何具体类名,也无需判断类型——它只面向接口编程,行为由运行时自动绑定。











