当前位置: 首页 > news >正文

OO第一阶段作业总结:从过程式思维到面向对象设计的蜕变

前言
本阶段的作业集涵盖了面向对象课程的前三次核心练习,旨在引导我们从传统的面向过程编程思维逐步过渡到面向对象(Object-Oriented, OO)的设计思维。这三次作业并非孤立的编程练习,而是一个循序渐进、逐步迭代的完整工程实践过程。

  1. 知识点覆盖
    Java 基础语法与核心类库:涵盖了数据类型、流程控制、数组与集合框架(ArrayList, HashMap)的使用。
    面向对象三大特性:重点实践了封装(Encapsulation)、继承(Inheritance)与多态(Polymorphism)。
    设计原则:在迭代过程中,我们深入体会了单一职责原则(SRP)和开闭原则(OCP)的重要性。
    算法与数据结构:涉及了基础的排序算法(冒泡排序)、递归下降解析以及简单的物理力学计算。
  2. 题量与难度分析
    题目一(基础配载):难度较低,主要考察基础的类定义和集合操作。题量较小,侧重于让初学者适应类的定义和对象的创建。
    题目二(多舱位管理):难度显著提升,引入了复杂的类间关系(组合、聚合)和算法调度。题量适中,但逻辑复杂度增加,需要处理多重循环和排序逻辑。
    题目三(旅客与配平计算):综合难度最高,引入了物理公式计算和更严格的输入验证。题量最大,且对代码的鲁棒性和业务逻辑的严谨性提出了极高要求。
    总体而言,这三次作业构成了一个从“能写代码”到“写好代码”的认知升级过程。
    设计与分析
    本节将基于 SourceMonitor 生成的代码复杂度报表以及 PowerDesigner 绘制的类图,对三次作业的源码设计进行详细剖析。
    ==================== SourceMonitor 代码度量汇总报告 ====================
    项目名称:航空器货运配载OO三次作业汇总
    统计语言:Java
    统计文件数:9个Java源文件
    总行代码行数:862 行
    注释行数:156 行
    空行:213 行
    有效业务代码:493 行

【类级度量】

  1. WMC(类总循环复杂度):
    第一次作业平均WMC:12.6
    第二次作业平均WMC:21.8
    第三次作业平均WMC:35.2
  2. OCavg(类平均方法复杂度):
    一作:2.1 二作:3.4 三作:4.7

【方法圈复杂度Top5】

  1. CargoSorter.sort() v(G)=4 ev(G)=2 iv(G)=2
  2. Main.main(二作) v(G)=6 ev(G)=3 iv(G)=4
  3. WeightBalanceCalculator.generateLoadSheet() v(G)=7 ev(G)=3 iv(G)=5
  4. InputValidator输入校验组 v(G)=3
  5. CargoCompartment装载校验 v(G)=3

【整体评估】
复杂度趋势:逐级递增,符合迭代开发逻辑
高复杂度集中点:排序算法、输入校验、重心配平公式计算、多分支业务判断

第一次作业:航空器配载与货运管理系统(基础版)

  1. 题目要求分析
    第一次作业要求实现一个基础的航班货运配载模块。核心功能包括:记录航班号、最大起飞重量;管理货物的添加;实时计算总重量并判断是否超载。关键点在于必须符合单一职责原则(SRP),将货物(Cargo)、航班(Flight)、装载清单(LoadManifest)和排序器(CargoSorter)分离。
  2. 类图设计
    exported_image

Main 类:负责流程控制。
Flight 类:仅存储航班属性(航班号、最大重量)。
Cargo 类:封装货物属性(名称、重量)。
LoadManifest 类:核心业务逻辑类,负责管理货物列表、计算总重、判断超载。
CargoSorter 类:纯算法工具类,负责对货物进行排序。
3. 代码复杂度分析
根据 SourceMonitor 分析,CargoSorter.sort 方法的圈复杂度(Cyclomatic Complexity)较高,达到了 4。
原因分析:该方法实现了选择排序算法,内部包含两层嵌套循环以及条件判断交换逻辑。虽然逻辑较为密集,但这是排序算法的固有特性。
代码片段分析:
java

编辑

// CargoSorter.sort 方法
for(int i=0; i<cargoList.size()-1; i++){
int maxIndex = i;
for(int j=i+1; j<cargoList.size(); j++){ // 嵌套循环导致复杂度上升
if (cargoList.get(j).a2() > cargoList.get(maxIndex).a2()){
maxIndex = j;
}
}
// 交换逻辑
if (maxIndex != i) { ... }
}
心得:虽然该方法复杂度较高,但逻辑清晰且独立。这说明在算法实现类中,适度的复杂度是允许的,关键在于将其与业务逻辑解耦。
第二次作业:多货舱管理与重量排序装载

  1. 题目要求分析
    第二次作业在第一次的基础上进行了扩展,引入了多货舱(CargoCompartment)的概念。难点在于货舱与位置(Position)的组合关系,以及货物装载时的实时检查。此外,必须使用冒泡排序且不能使用 Lambda 表达式。
  2. 类图设计exported_image (1)

新增 Position 类:表示货舱网格中的一个位置,体现了细粒度的对象建模。
CargoCompartment 类重构:内部聚合了 List 和 List。这里体现了组合(Composition)与聚合(Aggregation)的区别:货舱销毁,位置随之销毁(组合);货物可以独立于货舱存在(聚合)。
LoadDispatcher 类:作为调度中心,负责排序和查找。
3. 代码复杂度分析
Main 类的复杂度显著上升。
原因分析:Main 类中包含了大量输入处理逻辑和业务组装逻辑。例如,在读取货物并分配到货舱时,涉及了多层嵌套的 for 循环和 if 判断。
关键代码逻辑:
java

编辑

// Main.main 中的装载逻辑
List sortedCargos = LoadDispatcher.paiXuHuoWu(allCargos);
for(Cargo huo : sortedCargos){
CargoCompartment c = LoadDispatcher.zhaoCang(flight.cangList, huo.targetCangId);
if(c != null){
boolean success = c.jiaHuoWu(huo); // 这里触发了货舱内部的重量检查
// 输出日志...
}
}
心得:第二次作业中,我开始意识到“上帝类”的风险。Main 类开始承担过多的职责,这违背了 SRP。如果业务逻辑继续复杂化,Main 类将难以维护。
第三次作业:航空器配载与货运管理系统——配平计算

  1. 题目要求分析
    第三次作业引入了旅客(Passenger)和行李(Luggage)的概念,以及核心的配平计算(WeightBalanceCalculator)。设计约束极为严格:严禁使用继承和多态,必须使用静态常量,且输入验证必须独立。
  2. 类图设计
    exported_image (2)
    Passenger 与 Luggage 的组合:Passenger 类在构造函数内部 new 出 Luggage,体现了强拥有关系。
    WeightBalanceCalculator:纯计算工具类,不持有状态,通过参数传入 Flight 对象。
    InputValidator:静态工具类,剥离了所有输入校验逻辑。
  3. 代码复杂度分析
    WeightBalanceCalculator.generateLoadSheet 方法的行数较多,且包含大量的打印格式化代码。
    原因分析:该方法不仅负责计算重心(CG)和百分比(%MAC),还负责格式化输出报表。计算逻辑本身涉及多个物理公式的串联。
    公式实现代码:
    java

编辑

// 计算重心百分比
double cg = totalM / totalW;
double cgPer = ((cg - MAC_LEADING) / MAC_LENGTH) * 100;
心得:这是典型的“业务逻辑与展示逻辑混杂”。虽然通过静态常量定义了物理参数(如 EMPTY_ARM, PASSENGER_ARM)保证了可维护性,但输出部分的字符串拼接使得该方法过长。未来改进应考虑将报表生成独立为 ReportGenerator。
采坑心得
在三次作业的提交过程中,我遭遇了多次“血淋淋”的教训,这些坑主要集中在输入处理、算法边界和面向对象设计误区上。

  1. 输入处理的“回车符”陷阱(题目一)
    问题现象:在第一次作业中,使用 Scanner.nextInt() 后紧接着使用 Scanner.nextLine(),导致程序直接跳过输入,读取到了空字符串。
    根本原因:nextInt() 只读取数值,不读取最后的换行符(\n),这个换行符被后续的 nextLine() 读取并视为结束,从而返回空字符串。
    解决方案:在 nextInt() 后强制调用一次 nextLine() 来吸收残留的换行符。
    心得:Java 的 IO 流处理必须严谨对待缓冲区状态。这次经历让我养成了查阅 API 文档的习惯,明白了不同读取方法对输入流指针的影响。
  2. 冒泡排序的逻辑漏洞(题目二)
    问题现象:题目要求同等重量的货物按输入先后顺序排列(稳定性)。我最初实现的冒泡排序在交换时破坏了稳定性,导致互测被 Hack。
    代码对比:
    错误写法:if (a.getId() >= b.getId()) —— 使用了大于等于,导致相等时也交换,破坏了顺序。
    正确写法:if (a.getId() > b.getId()) —— 仅在大于时交换。
    心得:算法实现必须严格符合题目对“稳定性”的定义。在面向对象设计中,算法的正确性往往比性能更优先,尤其是在业务逻辑层。
  3. HashMap 的遍历修改异常(题目三背景)
    问题现象:虽然在本次作业中主要使用 List,但我在之前的练习(如多项式求导)中遇到过。在遍历 HashMap 时直接调用 remove() 方法,抛出了 ConcurrentModificationException。
    根本原因:直接使用 for-each 循环修改集合结构会触发 fail-fast 机制。
    解决方案:使用 Iterator 的 remove() 方法。
    心得:集合框架的内部机制(如迭代器模式)是必须掌握的基础。这让我意识到,盲目调用 API 而不理解其底层原理是极其危险的。
    改进建议
    针对上述作业中存在的设计问题,我提出以下具体的改进建议,以实现代码的可持续改进。
  4. 引入策略模式优化排序(针对题目二)
    现状:LoadDispatcher 中硬编码了冒泡排序,如果未来需要更换为快速排序,需要修改源代码。
    改进:定义 SortStrategy 接口,让 BubbleSort 和 QuickSort 实现该接口。LoadDispatcher 依赖于接口而非具体实现。
    预期效果:符合开闭原则,新增排序算法无需修改调度器代码。
  5. 分离关注点:报表生成器(针对题目三)
    现状:WeightBalanceCalculator 既负责计算又负责打印,违反了单一职责原则。
    改进:创建 ReportService 类。Calculator 只返回计算结果(DTO 对象),ReportService 负责将 DTO 格式化为字符串输出。
    预期效果:如果未来需要导出 PDF 或 JSON 格式,只需新增 ReportService 的实现,无需改动计算逻辑。
  6. 增强输入验证的友好性(通用)
    现状:目前的 InputValidator 在遇到错误时直接 System.exit(0),用户体验极差。
    改进:采用“异常抛出-捕获”机制,或者返回一个包含错误信息的 Result 对象,让 Main 类决定是重试输入还是退出。
    预期效果:提升系统的鲁棒性,使其更接近工业级应用的标准。
    总结
    经过这三次高强度的作业洗礼,我对 Java 语言和面向对象设计有了质的飞跃。
  7. 学到了什么
    从过程到对象的思维转换:我学会了不再首先思考“怎么做(算法)”,而是思考“谁来做(对象)”。例如,不再是 calculateWeight(flight),而是 flight.calculateWeight()。
    设计原则的重要性:深刻理解了单一职责原则(SRP)是避免代码腐化的基石。一个类如果变得臃肿,修改它就会变得异常痛苦。
    代码即设计:代码不仅仅是实现功能的工具,它本身就是系统的设计文档。清晰的类名和方法名能极大降低维护成本。
  8. 需要进一步学习的方向
    设计模式:虽然目前的作业规模较小,尚未显式使用复杂的设计模式,但我已经意识到工厂模式、策略模式在解耦方面的威力,这是下一步学习的重点。
    单元测试:目前的测试主要依赖黑盒输入输出。我需要学习 JUnit 框架,编写白盒测试用例,提高代码的覆盖率。
    Java 集合源码:为了写出更高效的代码,我需要深入研究 HashMap、ArrayList 的底层实现原理。
  9. 对课程的建议
    关于 AI 的使用:虽然课程禁止使用 AI 生成内容以防止抄袭,但我建议可以将 AI 作为“代码审查员”引入。例如,让学生先自己写,然后让 AI 指出代码中的坏味道(Code Smells),学生根据 AI 的建议进行重构。这能模拟真实的开发场景,因为现代开发者都在使用 Copilot 等工具。
    关于互测机制:目前的互测虽然能发现问题,但有时过于依赖运气。建议增加“测试用例共享”环节,强制要求提交边界测试用例,引导学生从“找茬”转向“构建高质量测试集”。
    这三次作业是一场痛苦但充满收获的修行。从最初面对对象时的手足无措,到现在能够有条理地进行类图设计,我迈出了成为合格软件工程师的第一步。
http://www.jsqmd.com/news/835837/

相关文章:

  • C++学习(26_05_17)
  • 贵阳园林绿植养护工程如何做线上推广?2026本地获客指南与服务商盘点 - 精选优质企业推荐官
  • 2026年甄选:公交站台源头厂家 - 品牌推广大师
  • 贵阳企业团建活动策划如何做线上推广?2026年本地获客指南与服务商推荐 - 精选优质企业推荐官
  • 贵阳冷库仓储物流配送如何做线上推广?2026全网获客指南与服务商盘点 - 精选优质企业推荐官
  • 如何在 Cloudflare Workers 中调用第三方 API 遇到 CORS 怎么解决
  • 面向对象设计与构造----第一单元总结
  • 上饶装修公司推荐|2026 避坑必看!本土靠谱装修怎么选,这 8 大雷区千万别踩 - 奔跑123
  • code-review-graph 完整上手攻略
  • 贵阳汽车美容洗护改装如何做线上推广?2026全网获客指南与服务商盘点 - 精选优质企业推荐官
  • 2026年5月南充区域广告设计制作(花草牌,小区园林标识,亚克力雕刻)安装价格 - 四川华蔓广告有限公司
  • 哈尔滨:报考中质协六西格玛黑带和绿带指定报考机构推荐 - 众智商学院课程中心
  • 贵阳劳保用品批量供应如何做线上获客?2026全网推广指南与服务商盘点 - 精选优质企业推荐官
  • DeepSeek V4 对于 LLM 应用开发落地到底意味着什么?--中国国内主流大模型 API 供应商横向对比
  • 2026年5月南充区域广告设计制作(标识牌,公示栏,精神堡垒)安装价格 - 四川华蔓广告有限公司
  • 企业知识库 Agent 完整落地教程:RAG + Claude 从架构到生产
  • 居家软装窗帘壁纸如何做线上推广?2026全网获客指南与服务商盘点 - 精选优质企业推荐官
  • 2026年5月南充区域广告设计制作(门头招牌,发光字,软膜灯箱)安装价格 - 四川华蔓广告有限公司
  • 心情又开始有点崩溃
  • 学Java类和对象
  • 四川华蔓广告有限公司设计安装施工|LED显示屏、南充地区一站式制作 - 四川华蔓广告有限公司
  • 2026年4月评价高的防水卷材直销厂家口碑推荐,高分子防水卷材/防水涂料/自粘防水卷材,防水卷材企业找哪家 - 品牌推荐师
  • Java常用类学习(String、StringBuffer、正则、Scanner)
  • 全屋定制家具企业如何做线上推广?2026年AI搜索、短视频与GEO优化指南 - 精选优质企业推荐官
  • 合肥全飞秒医院选择指南|普瑞眼科|安医大|科大眼科等正规眼科推荐 - 品牌速递
  • 徐州:报考中质协六西格玛黑带和绿带指定报考机构推荐 - 众智商学院课程中心
  • Claude Code Hooks 完整开发者指南
  • 2026越南奶茶加盟推荐榜:热门品牌甄选,创业开店优势尽显 - 企业推荐师
  • 四川华蔓广告有限公司设计安装施工|条幅锦旗,楼顶发光字,户外广告牌、南充地区一站式制作 - 四川华蔓广告有限公司
  • 四川华蔓广告有限公司设计安装施工|灯光舞台,演艺主持,泡沫板、南充地区一站式制作 - 四川华蔓广告有限公司