0

0

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

花韻仙語

花韻仙語

发布时间:2026-01-02 14:39:23

|

506人浏览过

|

来源于php中文网

原创

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

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

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

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

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

Chromox
Chromox

Chromox是一款领先的AI在线生成平台,专为喜欢AI生成技术的爱好者制作的多种图像、视频生成方式的内容型工具平台。

下载

示例代码实现

// 抽象基类:仅声明契约,不暴露验证器细节
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);
        if (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<Vehicle> 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 在调用侧做类型分发。

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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

156

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

88

2026.01.26

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1089

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

58

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

63

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

27

2025.11.27

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
手把手实现数据传输编码
手把手实现数据传输编码

共1课时 | 768人学习

PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

【李炎恢】ThinkPHP8.x 后端框架课程
【李炎恢】ThinkPHP8.x 后端框架课程

共50课时 | 4.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号