0

0

如何通过面向对象多态实现无条件分支的统一验证调用

花韻仙語

花韻仙語

发布时间:2026-01-02 15:09:08

|

675人浏览过

|

来源于php中文网

原创

如何通过面向对象多态实现无条件分支的统一验证调用

本文介绍一种基于依赖注入与模板方法模式的设计方案:将各类校验器(如轮胎、刹车、油量)在对象创建后预先注入子类实例,使抽象父类 `vehicle` 的 `runallvalidations()` 方法可无参数、无 `if` 分支地完成类型专属的完整校验流程。

在面向对象设计中,避免运行时类型判断(如 instanceof 或 if-else 链)的关键在于将“决策权”前移至对象构建阶段,而非执行阶段。本方案摒弃了“向通用方法传入所有可能校验器”的冗余方式,也规避了显式类型检查的坏味道,转而采用 “校验器注入 + 模板方法” 的组合策略,既保持接口统一性,又确保行为专一性。

Favird No-Code Tools
Favird No-Code Tools

无代码工具的聚合器

下载

✅ 核心设计思想

  • 职责分离:Vehicle 定义统一入口 runAllValidations(),但不参与具体校验逻辑;各子类负责声明自身所需的校验器字段,并在 runAllValidations() 中按需调用对应 checkXxx() 方法。
  • 依赖前置注入:校验器(TireValidator、BrakeValidator、GasValidator)不在调用时传入,而是在对象初始化后通过 setXxxValidator() 显式注入——这使校验逻辑完全解耦于调用上下文。
  • 多态驱动执行:main 中只需持有 Vehicle 类型引用,调用 runAllValidations() 即可自动触发子类定制化逻辑,真正实现“一个接口,多种实现”。

? 完整代码示例

// 抽象基类:定义公共校验能力与统一入口
abstract class Vehicle {
    protected Tire tire;
    protected TireValidator tireValidator;

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

    protected void checkTire() {
        if (tireValidator != null) {
            tireValidator.check(tire);
        } else {
            throw new IllegalStateException("TireValidator not set for " + getClass().getSimpleName());
        }
    }

    public abstract void runAllValidations();
}

// 子类 Bike:仅关注轮胎 + 刹车
class Bike extends Vehicle {
    private Brakes brakes;
    private BrakeValidator brakeValidator;

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

    protected void checkBrakes() {
        if (brakeValidator != null) {
            brakeValidator.check(brakes);
        } else {
            throw new IllegalStateException("BrakeValidator not set for Bike");
        }
    }

    @Override
    public void runAllValidations() {
        checkTire();   // 复用父类逻辑
        checkBrakes(); // 扩展自身逻辑
    }
}

// 子类 Car:仅关注轮胎 + 油量
class Car extends Vehicle {
    private Gas gas;
    private GasValidator gasValidator;

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

    protected void checkGas() {
        if (gasValidator != null) {
            gasValidator.check(gas);
        } else {
            throw new IllegalStateException("GasValidator not set for Car");
        }
    }

    @Override
    public void runAllValidations() {
        checkTire(); // 复用父类逻辑
        checkGas();  // 扩展自身逻辑
    }
}

? 使用方式(零条件、零冗余参数)

public static void main(String[] args) {
    // 实例化校验器(假设已实现)
    TireValidator tireValidator = new DefaultTireValidator();
    BrakeValidator brakeValidator = new DefaultBrakeValidator();
    GasValidator gasValidator = new DefaultGasValidator();

    // 构建具体车辆并注入其专属校验器
    Bike bike = new Bike();
    bike.setTireValidator(tireValidator);
    bike.setBrakeValidator(brakeValidator);

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

    // 统一调用 —— 无需 if,无需传参,无需关心具体类型
    List<Vehicle> vehicles = List.of(bike, car);
    vehicles.forEach(Vehicle::runAllValidations); // ✅ 多态自动分发

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

⚠️ 注意事项与最佳实践

  • 空校验防护:示例中在 checkXxx() 内添加了 null 检查并抛出明确异常,避免静默失败;生产环境建议结合 Objects.requireNonNull() 或构造器强制注入(如使用 Spring 的 @RequiredArgsConstructor)进一步强化契约。
  • 扩展性友好:新增车辆类型(如 Truck 需校验载重与灯光)只需继承 Vehicle、注入对应校验器、重写 runAllValidations(),无需修改任何现有类或条件逻辑
  • 替代进阶方案:若校验器生命周期复杂(如需复用、代理、AOP 增强),可考虑引入 ValidatorRegistry 或依赖注入框架(如 Spring)管理校验器 Bean,再通过 @Autowired 自动装配到子类中,进一步降低手动注入成本。

该方案以简洁、可读、可维护的方式,完美践行了 “开闭原则”“里氏替换原则”,是消除类型判断、提升多态价值的经典实践。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

阿里巴巴推出的全能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什么意思的相关文章,供大家免费阅读。

846

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

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

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

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