软件架构风格系列(2):面向对象架构
文章目录
- 引言
- 一、什么是面向对象架构风格
- 1. 定义与核心概念
- 2. 优点与局限性
- 二、业务建模:用对象映射现实世界
- (一)核心实体抽象
- 1. 员工体系
- 2. 菜品体系
- (二)封装:隐藏实现细节
- 三、继承实战:构建员工体系层级
- (一)抽象类设计
- (二)子类实现
- 四、多态实践:同一接口不同实现
- (一)接口定义
- (二)具体实现
- (三)多态调用
- 五、架构优势与适用场景
- (一)OOP 核心优势
- (二)适用场景
- (三)避坑指南
- 总结
引言
大家好,我是沛哥儿。最近在带团队重构管理系统时,发现很多小伙伴对面向对象(OOP)的理解还停留在 “类和对象” 的表面。今天就通过这个实战案例,带大家深度解析 OOP 的三大核心特性 —— 封装、继承、多态,以及如何用 OOP 思维构建可扩展的系统架构。
一、什么是面向对象架构风格
1. 定义与核心概念
面向对象架构(Object-Oriented Architecture, OOA)基于对象、类、继承、多态等机制构建软件系统。核心思想是将现实世界中的实体抽象为对象,通过封装数据与行为,使对象成为独立的功能单元。
面向对象架构通过封装、继承、多态等机制,为复杂系统提供清晰的设计范式。结合设计模式与云原生技术,其在现代软件开发中持续发挥核心作用。
关键特点
- 封装性:数据与行为绑定,隐藏内部实现细节
- 模块化:系统分解为独立对象/类,降低耦合度
- 继承与多态:支持代码重用与动态行为扩展
- 消息机制:对象交互通过方法调用或事件触发
2. 优点与局限性
优点:
- 高可重用性(代码模块化、继承机制)
- 灵活维护(封装、松耦合,便于需求变更)
- 适合复杂系统建模(如业务逻辑、现实实体映射)
局限性:
- 性能损耗(消息传递开销)
- 大型系统设计复杂度(需合理架构划分)
- 依赖开发环境(如语言支持、工具生态)
二、业务建模:用对象映射现实世界
(一)核心实体抽象
任何复杂系统的第一步都是建立正确的领域模型。在餐厅场景中,我们可以抽象出以下核心对象:
1. 员工体系
抽象父类 Employee:定义所有员工的公共属性(工号、姓名、岗位)和抽象方法(工作、计算工资)
子类 Waiter:新增服务区域属性,实现点餐和送餐具体逻辑
子类 Chef:记录擅长菜系,实现烹饪和食材检查功能
2. 菜品体系
接口 Dish:定义所有菜品的统一接口(获取名称、价格、准备步骤)
具体实现类:中餐 / 西餐分别实现不同的 prepare () 方法,体现多态性
(二)封装:隐藏实现细节
看一个订单对象的封装设计:
public class Order {private String orderId;private List<Dish> dishes = new ArrayList<>();private Customer customer;private OrderStatus status;// 封装状态变更逻辑public void confirmOrder() {if (status == OrderStatus.NEW) {status = OrderStatus.CONFIRMED;notifyKitchen();}}// 暴露业务接口而非底层数据public double calculateTotalPrice() {return dishes.stream().mapToDouble(Dish::getPrice).sum();}private void notifyKitchen() {// 调用系统接口,细节对外隐藏}
}
核心原则:
- 所有属性私有化,通过公共方法操作
- 复杂业务逻辑封装在对象内部
- 对外暴露最小必要接口
三、继承实战:构建员工体系层级
(一)抽象类设计
public abstract class Employee {protected String id;protected String name;protected double baseSalary;// 强制子类实现的抽象方法public abstract double calculateSalary();// 模板方法:公共逻辑放在父类public void punchIn(LocalDateTime time) {System.out.println(name + " 于" + time + "打卡上班");// 记录考勤的公共逻辑}
}
(二)子类实现
服务员类:
public class Waiter extends Employee {private String serviceArea;public Waiter(String id, String name, double baseSalary, String serviceArea) {this.id = id;this.name = name;this.baseSalary = baseSalary;this.serviceArea = serviceArea;}@Overridepublic double calculateSalary() {// 底薪 + 提成计算逻辑return baseSalary + getTips();}private double getTips() {// 计算小费的具体逻辑return 500;}
}
厨师类:
public class Chef extends Employee {private String[] specialties;public Chef(String id, String name, double baseSalary, String[] specialties) {this.id = id;this.name = name;this.baseSalary = baseSalary;this.specialties = specialties;}@Overridepublic double calculateSalary() {// 底薪 + 菜品提成return baseSalary + calculateDishBonus();}private double calculateDishBonus() {// 根据烹饪数量计算奖金return 1000;}
}
继承带来的优势:
✅ 代码复用:考勤逻辑只需在父类实现一次
✅ 层次清晰:通过 UML 类图可直观看到继承关系
✅ 强制契约:抽象方法保证子类必须实现核心逻辑
四、多态实践:同一接口不同实现
(一)接口定义
public interface Payment {boolean pay(double amount);void generateReceipt();
}
(二)具体实现
现金支付:
public class CashPayment implements Payment {@Overridepublic boolean pay(double amount) {System.out.println("现金支付" + amount + "元");return true;}@Overridepublic void generateReceipt() {System.out.println("打印现金支付小票");}
}
扫码支付:
public class QRCodePayment implements Payment {@Overridepublic boolean pay(double amount) {System.out.println("扫码支付" + amount + "元");return true;}@Overridepublic void generateReceipt() {System.out.println("发送电子小票到手机");}
}
(三)多态调用
public class OrderService {public void checkout(Order order, Payment paymentMethod) {double total = order.calculateTotalPrice();if (paymentMethod.pay(total)) {order.setStatus(OrderStatus.PAID);paymentMethod.generateReceipt();}}
}// 使用时无需关心具体支付类型
OrderService service = new OrderService();
service.checkout(order, new CashPayment()); // 现金支付
service.checkout(order, new QRCodePayment()); // 扫码支付
多态的核心价值:
🔥 可替换性:支付方式可随时新增或修改
🔥 扩展性:新增支付类型无需修改原有代码
🔥 解耦性:订单服务与具体支付实现分离
五、架构优势与适用场景
(一)OOP 核心优势
特性 | 优势体现 | 案例说明 |
---|---|---|
封装 | 数据安全 / 降低复杂度 | 订单对象隐藏状态变更细节 |
继承 | 代码复用 / 层次化设计 | 员工体系共享考勤和薪资计算逻辑 |
多态 | 灵活扩展 / 接口统一 | 新增支付方式无需修改核心业务逻辑 |
(二)适用场景
✅ 业务实体复杂且存在层级关系(如电商商品分类)
✅ 需要频繁扩展新功能(如新增支付方式、会员类型)
✅ 追求代码复用和可维护性(大型团队协作项目)
(三)避坑指南
- 避免滥用继承:优先使用组合(Has-A)而非继承(Is-A)
- 接口最小化:每个接口只定义必要方法
- 里氏替换原则:子类必须完全实现父类契约
总结
面向对象架构的本质是 “通过抽象和建模,让代码像现实世界一样易于理解和扩展”。掌握三大特性的核心用法后,我们可以:
- 用封装构建健壮的对象边界
- 用继承建立清晰的层级关系
- 用多态实现灵活的扩展能力
当然,OOP 并非银弹,需要结合具体业务场景使用。
如果你在实际项目中遇到 OOP 相关问题,欢迎在评论区留言讨论~
所有图片来源网络
相关文章:

软件架构风格系列(2):面向对象架构
文章目录 引言一、什么是面向对象架构风格1. 定义与核心概念2. 优点与局限性二、业务建模:用对象映射现实世界(一)核心实体抽象1. 员工体系2. 菜品体系 (二)封装:隐藏实现细节 三、继承实战:构建…...
ngx_http_random_index_module 模块概述
一、使用场景 随机内容分发 当同一目录下存放多份等价内容(如多张轮播图、不同版本静态页面等)时,可通过随机索引实现负载均衡或流量分散。A/B 测试 通过目录请求自动随机分配用户到不同测试组,无需后端逻辑参与。动态“首页”选…...

go-zero(十八)结合Elasticsearch实现高效数据检索
go-zero结合Elasticsearch实现高效数据检索 1. Elasticsearch简单介绍 Elasticsearch(简称 ES) 是一个基于 Lucene 库 构建的 分布式、开源、实时搜索与分析引擎,采用 Apache 2.0 协议。它支持水平扩展,能高效处理大规模数据的存…...

AM32电调学习解读九:ESC上电启动关闭全流程波形分析
这是第九篇,前面的文章把各个模块的实现都介绍了一轮,本章是从运行的角度结合波形图,把整个流程走一遍。 先看下一运行的配置,我把一些配置关闭了,这样跑起来会好分析一些,不同配置跑起来效果会有差异。使用…...
怎么打包发布到npm?——从零到一的详细指南
怎么打包发布到npm?——从零到一的详细指南 目录 怎么打包发布到npm?——从零到一的详细指南一、准备工作1. 注册 npm 账号2. 安装 Node.js 和 npm 二、初始化项目三、编写你的代码四、配置 package.json五、打包你的项目六、登录 npm七、发布到 npm八、…...
NX二次开发C#---遍历当前工作部件实体并设置颜色
该代码片段展示了如何在Siemens NX软件中使用C#进行自动化操作。通过NXOpen和UFSession API,代码首先获取当前工作部件,并遍历其中的所有实体。对于每个实体,代码检查其类型和子类型是否为“实体”,如果是,则将其颜色设…...
如何用体育数据做分析:从基础统计到AI驱动的决策科学
一、体育数据分析的演进与价值创造 体育数据分析已从简单的比分记录发展为融合统计学、计算机科学和运动科学的交叉学科。现代体育组织通过数据分析可以实现: 竞技表现提升:勇士队利用投篮热图优化战术布置 商业价值挖掘:曼联通过球迷行为数…...
09、底层注解-@Import导入组件
09、底层注解-Import导入组件 Import是Spring框架中的一个注解,用于将组件导入到Spring的应用上下文中。以下是Import注解的详细介绍: #### 基本用法 - **导入配置类** java Configuration public class MainConfig { // 配置内容 } Configuration Impo…...

【notes】VScode 使用总结
文章目录 扩展 c/cwindows7 系统下 c/c 自动升级导致的插件无法正常使用 设置 文件格式设置打开文件的默认格式 扩展 c/c windows7 系统下 c/c 自动升级导致的插件无法正常使用 问题 1. c/c扩展的1.25.x版本不再支持windows7 系统,当设置VScode自动升级拓展插件时…...

【论文阅读】KIMI K1.5: SCALING REINFORCEMENT LEARNING WITH LLMS
KIMI K1.5: SCALING REINFORCEMENT LEARNING WITH LLMS Scaling的解释: 通过系统性的方法扩展强化学习算法的能力,使其能够处理更复杂的问题、更大的状态/动作空间、更长的训练周期或更高效的资源利用 原文摘要: 研究背景与问题定位 传统预训…...
云服务器开发软件操作步骤
云服务器开发软件的主要步骤。通常,这包括选择云服务提供商、配置服务器环境、开发、测试、部署、维护等阶段。每个阶段都需要详细解释,可能需要分步骤说明。例如,选择云服务提供商时,需要考虑AWS、阿里云、腾讯云等,比…...

Qwen3 - 0.6B与Bert文本分类实验:深度见解与性能剖析
Changelog [25/04/28] 新增Qwen3-0.6B在Ag_news数据集Zero-Shot的效果。新增Qwen3-0.6B线性层分类方法的效果。调整Bert训练参数(epoch、eval_steps),以实现更细致的观察,避免严重过拟合的情况。 TODO: 利用Qwen3-0.6…...
4.6 sys模块
sys --- 仅作了解 面试之前冲击一下 python的垃圾回收机制 import sys # 1. api_version : 获取python的内部版本号 print(sys.api_version) #1013 # 2. copyright: 获取cpython的版本 print(sys.copyright) #3.getfilesystemencoding() getdefaultencoding():获…...

UWB定位方案在水力发电站人员安全的应用推荐
一、行业应用背景 水力发电站具有环境复杂(金属设备密集、高温高压区域多)、安全风险高(人员误入高危区域易引发事故)等特点,传统定位技术难以满足精度与可靠性要求。品铂科技基于UWB的高精度定位系统已在多…...
青少年编程与数学 02-019 Rust 编程基础 16课题、包、单元包及模块
青少年编程与数学 02-019 Rust 编程基础 16课题、包、单元包及模块 一、包1. **什么是 Crate?**2. **Crate 的类型**3. **Crate 的结构**4. **使用 Crate**5. **创建和管理 Crate**6. **发布 Crate**7. **Crate 的优势**8. **示例**创建一个 library crate 二、单元…...
bat 批处理获取日期、时间
在Windows批处理脚本编程中,获取当前日期和时间是一项常见且重要的操作。 1. 获取当前日期和时间的基本脚本 echo off for /F "tokens2" %%i in (date /t) do set mydate%%i set mytime%time% echo Current time is %mydate%:%mytime%输出示例ÿ…...
手写tomcat:基本功能实现(3)
TomcatRoute类 TomcatRoute类是Servlet容器,是Tomcat中最核心的部分,其本身是一个HashMap,其功能为:将路径和对象写入Servlet容器中。 package com.qcby.config;import com.qcby.Util.SearchClassUtil; import com.qcby.servlet…...
Spring Cloud Seata 快速入门及生产实战指南
文章目录 前言一、快速入门(AT模式)二、生产环境实战要点总结 前言 上一篇博客带大家深入解析Seata的核心原理及架构,理解了“为什么需要分布式事务”以及“Seata如何解决数据一致性问题”,相信大家已经对分布式事务的理论框架有…...
电商平台自动化
为什么要进行独立站自动化 纯人工测试人力成本高,相对效率低 回归测试在通用模块重复进行人工测试,测试效率低 前期调研备选自动化框架(工具): Katalon Applitools Testim 阿里云EMAS Playwright Appium Cypress 相关…...
Java微服务架构实战:Spring Boot与Spring Cloud的完美结合
Java微服务架构实战:Spring Boot与Spring Cloud的完美结合 引言 随着云计算和分布式系统的快速发展,微服务架构已成为现代软件开发的主流模式。Java作为企业级应用开发的核心语言,结合Spring Boot和Spring Cloud,为开发者提供了…...
王树森推荐系统公开课 召回11:地理位置召回、作者召回、缓存召回
GeoHash 召回 属于地理位置召回,用户可能对附近发生的事情感兴趣。GeoHash 是一种对经纬度的编码,地图上每个单位矩形的 GeoHash 的前几位是相同的,GeoHash 编码截取前几位后,将相同编码发布的内容按时间顺序(先是时间…...

无刷直流水泵构成及工作原理详解--【其利天下技术】
无刷直流水泵是相对于有刷直流泵而言的。 一:无刷直流水泵简介 无刷直流水泵即BLDC PUMP,其中“BL”意为“无刷”,DC即直流电机。 无刷直流水泵(BLDC PUMP)以电子换向器取代了机械换向器,所以无刷直流水泵既具有直流电机良好的调…...
less中使用 @supports
在Less中使用supports supports 是CSS的条件规则,用于检测浏览器是否支持特定的CSS属性或值。在Less中,你可以像在普通CSS中一样使用supports,同时还能利用Less的特性来增强它。 基本用法 /* 检测浏览器是否支持display: flex */ supports …...

大数据:新能源汽车宇宙的未来曲率引擎
** 发布日期:2025-05-14** 关键词:大数据、新能源、机器学习、碳中和、CSDN爆款 1. 大数据科普:定义、特征与技术核心 1.1 什么是大数据? 大数据(Big Data)指规模巨大、类型多样、生成速度快且价值密度低…...

【Java ee】关于抓包软件Fiddler Classic的安装与使用
Web Debugging Proxy Tool | Fiddler Classic 安装网站↑ 下载好安装包之后,双击一路next就可以了 一、抓包软件 电脑上安装了抓包软件之后,抓包软件就可以监听你的网卡上通过的数据。 本来是你的客户端通过网卡,把数据发给目标服务器&a…...
第五部分:第五节 - Express 路由与中间件进阶:厨房的分工与异常处理
随着你的 Express 应用变得越来越大,所有的路由和中间件都写在一个文件里会变得难以管理。这时候就需要将代码进行拆分和组织。此外,一个健壮的后端应用必须能够优雅地处理错误和一些常见的 Web 开发问题,比如跨域。 路由模块化 (express.Ro…...
在 CentOS 7.9 上部署 node_exporter 并接入 Prometheus + Grafana 实现主机监控
文章目录 在 CentOS 7.9 上部署 node_exporter 并接入 Prometheus Grafana 实现主机监控环境说明node_exporter 安装与配置下载并解压 node_exporter创建 Systemd 启动服务验证服务状态验证端口监听 Prometheus 配置 node_exporter 监控项修改 prometheus.yml重新加载 Prometh…...

C++--内存管理
内存管理 1. C/C内存分布 在C语言阶段,常说局部变量存储在栈区,动态内存中的数据存储在堆区,静态变量存储在静态区(数据段),常量存储在常量区(代码段),其实这里所说的栈…...
Java实现PDF加水印功能:技术解析与实践指南
Java实现PDF加水印功能:技术解析与实践指南 在当今数字化办公环境中,PDF文件因其跨平台兼容性和格式稳定性而被广泛应用。然而,为了保护文档的版权、标记文档状态(如“草稿”“机密”等)或增加文档的可追溯性…...
Django + Celery 打造企业级大模型异步任务管理平台 —— 从需求到完整实践(含全模板源码)
如需完整工程文件(含所有模板),可回复获取详细模板代码。 面向人群:自动化测试工程师、企业中后台开发人员、希望提升效率的 AI 业务从业者 核心收获:掌握 Django 三表关系设计、Celery 异步任务实践、基础 Web 交互与前后端分离思路,源码可直接落地,方便二次扩展 一、系…...