如何在不使用 if 判断的前提下,通过父类单个方法统一调用子类特有验证逻辑?

通过依赖注入将对应验证器预设到子类实例中,使 `runallvalidations()` 成为无参、类型安全、开闭原则友好的纯多态调用。

在面向对象设计中,实现“对扩展开放、对修改关闭”(Open/Closed Principle)的关键在于将行为差异下沉至具体子类,并通过多态消除运行时类型检查。针对 Vehicle 体系中不同子类需执行差异化验证(Bike 需验轮胎 + 刹车,Car 需验轮胎 + 油量)的场景,最佳实践是避免在调用处(如 main)或抽象层硬编码参数组合或条件分支,而是采用验证器预绑定 + 无参抽象方法的设计模式。

✅ 推荐方案:验证器注入 + 无参多态调用

核心思想:在创建子类实例后、调用前,主动为其注入其专属的验证器(TireValidator、BrakeValidator 或 GasValidator),使 runAllValidations() 完全解耦于外部参数,仅依赖自身已持有的依赖项。

示例代码实现

// 抽象基类:仅声明契约,不暴露验证器细节
abstract class Vehicle {
    protected Tire tire;

    // 公共验证逻辑(由子类复用)
    protected void checkTire(TireValidator validator) {
        if (validator != null) validator.check(tire);
    }

    // 统一入口:无参、无条件、纯多态
    public abstract void runAllValidations();
}

// Bike:持有自身所需验证器引用
class Bike extends Vehicle {
    private Brakes brakes;
    private TireValidator tireValidator;
    private BrakeValidator brakeValidator;

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

    public void setBrakeValidator(BrakeValidator validator) {
        this.brakeValidator = validator;
    }

    @Override
    public void runAllValidations() {
        checkTire(tireValidator);     // 复用父类公共逻辑
        if (brakeValidator != null) {
            brakeValidator.check(brakes);
        }
    }
}

// Car:同理,按需绑定
class Car extends Vehicle {
    private Gas gas;
    private TireValidator tireValidator;
    private GasValidator gasValidator;

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

    public void setGasValidator(GasValidator validator) {
        this.gasValidator = validator;
    }

    @Override
    public void runAllValidations() {
        checkTire(tireValidator);
        i

f (gasValidator != null) { gasValidator.check(gas); } } }

调用端(main)简洁、类型安全、无 if

public static void main(String[] args) {
    // 创建验证器
    TireValidator tireValidator = new TireValidatorImpl();
    BrakeValidator brakeValidator = new BrakeValidatorImpl();
    GasValidator gasValidator = new GasValidatorImpl();

    // 创建并注入依赖
    Bike bike = new Bike(/*...*/);
    bike.setTireValidator(tireValidator);
    bike.setBrakeValidator(brakeValidator);

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

    // ✅ 统一调用 —— 无需传参、无需 instanceof、无需 if
    List vehicles = List.of(bike, car);
    vehicles.forEach(Vehicle::runAllValidations); // 多态自动分发

    // 或单独调用
    bike.runAllValidations(); // → checkTire + checkBrakes
    car.runAllValidations();  // → checkTire + checkGas
}

⚠️ 注意事项与增强建议

  • 空值防护:示例中已加入 if (validator != null),实际项目中可结合 Objects.requireNonNull() 或使用 Optional 显式表达依赖可选性。
  • 构造时注入更优:为提升不可变性与线程安全性,推荐将验证器通过构造函数注入(如 new Bike(tireValidator, brakeValidator)),而非 setter —— 这进一步杜绝了“未配置即调用”的风险。
  • 接口细化(进阶):若验证器种类持续增长,可定义标记接口(如 TireValidatable, BrakeValidatable),配合 instanceof 在工厂/构建器中 使用(非业务逻辑层),实现更灵活的组合装配。
  • Spring 等框架支持:在 DI 容器环境中,可直接通过 @Autowired 或构造注入自动完成验证器绑定,彻底消除手动 setXxxValidator() 调用。

✅ 总结

该方案彻底规避了两种反模式:
❌ 不再传递冗余参数(如向 Bike 传 GasValidator);
❌ 不再使用 instanceof / if-else 在调用侧做类型分发。

它将类型相关的行为决策权交还给子类自身,符合里氏替换原则与单一职责原则,同时保持了客户端代码的高度简洁与可维护性。多态不是语法糖,而是解耦复杂条件逻辑的基石。