如何在不使用 if 条件的前提下,通过父类单个方法调用实现子类差异化验证逻辑

本文介绍一种基于**依赖注入 + 模板方法模式**的优雅设计:将具体验证器(如 tirevalidator、brakevalidator)在创建子类实例时预先注入,使 `runallvalidations()` 成为无参、无分支、类型安全的纯多态调用。

在面向对象设计中,当需要对不同子类执行“共性+个性”混合操作(如统一校验轮胎,再分别校验刹车或油量),又希望避免 instanceof 或参数冗余等反模式时,关键在于将“行为差异”转化为“状态差异”——即把验证器作为对象的内部状态(成员变量)而非方法参数,从而让多态方法自然解耦。

以下是一个完整、可运行的设计方案:

✅ 核心设计原则

  • 职责分离:Vehicle 定义通用骨架与公共能力(如 checkTire()),不感知具体验证器类型;
  • 延迟绑定:验证器通过 setter 注入(或构造器注入),确保每个子类只持有其真正需要的验证器;
  • 零条件调度:runAllValidations() 在子类中直接组合已注入的验证逻辑,无需任何 if 或类型判断。

? 代码实现

// 抽象基类:定义公共状态与能力
abstract class Vehicle {
    protected Tire tire;
    protected TireValidator tireValidator;

    public void setTireValidator(TireValidator validator) {
        this.tireValidator = validator;
    }

    protected void checkTire() {
        if (tireValidator == null) {
            throw new IllegalStateException("TireValidator not set");
        }
        tireValidator.check(tire);
    }

    public abstract void runAllValidations();
}

// 子类 Bike:仅需 TireValidator + BrakeValidator
class Bike extends Vehicl

e { private Brakes brakes; private BrakeValidator brakeValidator; public void setBrakeValidator(BrakeValidator validator) { this.brakeValidator = validator; } protected void checkBrakes() { if (brakeValidator == null) { throw new IllegalStateException("BrakeValidator not set"); } brakeValidator.check(brakes); } @Override public void runAllValidations() { checkTire(); // 公共逻辑 checkBrakes(); // 特有逻辑 } } // 子类 Car:仅需 TireValidator + GasValidator class Car extends Vehicle { private Gas gas; private GasValidator gasValidator; public void setGasValidator(GasValidator validator) { this.gasValidator = validator; } protected void checkGas() { if (gasValidator == null) { throw new IllegalStateException("GasValidator not set"); } gasValidator.check(gas); } @Override public void runAllValidations() { checkTire(); // 公共逻辑 checkGas(); // 特有逻辑 } }

▶️ 使用示例(主程序)

public class ValidationDemo {
    public static void main(String[] args) {
        // 创建验证器实例
        TireValidator tireValidator = new TireValidator();
        BrakeValidator brakeValidator = new BrakeValidator();
        GasValidator gasValidator = new GasValidator();

        // 构造具体车辆并注入其所需验证器
        Bike bike = new Bike();
        bike.setTireValidator(tireValidator);
        bike.setBrakeValidator(brakeValidator);

        Car car = new Car();
        car.setTireValidator(tireValidator);
        car.setGasValidator(gasValidator);

        // ✅ 统一调用 —— 完全多态,无 if,无冗余参数
        List vehicles = List.of(bike, car);
        vehicles.forEach(Vehicle::runAllValidations); // 输出:Tire OK → Brakes OK;Tire OK → Gas OK

        // 也可单独调用
        car.runAllValidations();
        bike.runAllValidations();
    }
}

⚠️ 注意事项与进阶建议

  • 空安全:示例中加入了 null 检查,生产环境推荐配合 Objects.requireNonNull() 或使用 Optional 封装验证器;
  • 构造器注入更优:若验证器是必需依赖(即对象创建后必须可用),应优先使用构造器注入替代 setter,提升不可变性与初始化安全性;
  • 扩展性保障:新增子类(如 Truck 需校验 Cargo 和 Axle)只需继承 Vehicle、添加对应字段/校验方法、重写 runAllValidations(),完全不影响现有代码;
  • 避免“胖接口”陷阱:不采用“传入所有验证器”的方式,从根本上消除参数污染和调用方认知负担。

该方案以简洁的面向对象实践,实现了开闭原则(对扩展开放、对修改关闭)与里氏替换原则(子类可安全替换父类)的双重落地——正是多态价值的典型体现。