题目集8~9的总结性Blog

1. 前言

知识点总结:

  这两次题目集主要还是锻炼我们的类设计能力,其中有一些题目是扩展了之前的题目,加了一些条件,改了一些判断方式,但是代码的大体逻辑不变,让我们深刻认识到了遵循设计原则的重要性,如开闭原则和依赖倒置原则可以让我们在较少的改动下完成这次题目.

  知识点有用到继承,多态,集合等,这次的9题目集的第三题也让我们意识到了,集合中的多态性可以怎么运用来简化代码.

  两次题目集都是侧重于锻炼我们的类设计能力,但是题目集9更侧重于系统扩展.

题量与难度

  两个题目集的题量都是3道,题目集8是第一道点面设计与第二道雨刷器功能的扩展,重构,第三道的航空货运管理系统的初次设计;题目集9是第一题的点面设计的魔方类的设计与第二题的点面设计,第三题的航空货运管理系统需求改变. 两次题目集都是呈现难度递增的趋势.

2. 设计与分析

题目集8:

源码分析:

类图

一、核心类功能

类名 功能简述
Customer 存储客户基础信息(姓名、电话、地址)
Cargo 描述货物属性(名称、尺寸、重量),计算计费重量(体积与实际重量取最大值)
Flight 存储航班信息(航班号、载重限制)
OrderDate 存储订单日期、收发件人信息(订单号、姓名、地址等)
FreightCalculate
根据货物重量计算运费费率和金额(继承自抽象类)
Order 整合订单全量信息,打印客户详情与货物明细(继承自抽象类)
Main 程序入口,负责输入数据、创建对象、校验逻辑(如航班载重)

二、类间关键关系

继承有

AbsCalculateFreight <|-- FreightCalculate
AbsOrder <|-- Order

组合有

Order *-- Flight : 包含
Order *-- Cargo : 包含多个
Order *-- OrderDate : 包含
Order *-- Customer : 包含
Order *-- FreightCalculate : 包含多个
FreightCalculate *-- Cargo : 依赖货物数据

复杂度分析

1. 文件太大,结构混乱

  • 416 行代码全放在一个文件里,虽然包含 9 个类,但应该拆分成多个文件(1 个类  1 个文件)。

  • 0% 注释,时间久了自己都看不懂,尤其是复杂方法 FreightCalculate.calculateRate()。

2. 部分方法逻辑较复杂

  • 最复杂的方法 calculateRate()复杂度=5(一般超过 5 就要优化),建议:

    • 拆分成多个小方法

    • 用 switch或策略模式替代 if-else

  • 最深嵌套 3 层(第 23 行),可以尝试减少嵌套,用 return  提前返回。

3. 类设计可能不合理

  • 平均每个类有 7.11 个方法,有些类可能做了太多事情,违反单一职责原则.

设计亮点与不足:

代码类的设计较为合理,可扩展性较好,虽然每个类看似方法都挺多,但有许多Getter,Setter方法,没有违法单一职责.

但我为了方便将所有代码全部放进一个文件里导致文件太大,而且也没有在一些关键地方添加注释让之后的阅读难度较高.

代码不算太糟,但如果不拆分文件和加注释,以后维护会很痛苦!

心得:

  在计算订单总重量(kg)时,下意识以为就是实际的重量和,但题目的测试是用计费重量计算的导致我一直没有发现问题,浪费了许多时间,后来自己突然发现后才看到评论区已经有人说了这个问题了😑,让我意思到与同学多讨论可以减少这种没有意义的问题.

题目集9:

源码分析:

类图

一、核心类功能

类名 功能简述
Customer 用于存储客户的基础信息,涵盖客户类型、客户代码、客户姓名、客户电话以及客户地址等内容,提供属性的读写方法以方便对客户信息进行管理和操作 。
Cargo 主要描述货物的属性,包括货物类型、货物代码、货物名称、宽度、高度、长度、重量等。具备计算体积重量和计费重量(取体积重量与实际重量中的较大值)的功能,为后续运费计算等业务提供关键数据支持 。
Flight 负责存储航班相关信息,如航班号、出发城市、目的城市、航班日期以及最大载重。通过属性的访问和修改方法,实现对航班信息的管理,用于判断货物能否装载到该航班 。
OrderDate 用于存储订单日期,以及收发件人的详细信息,包括发件人姓名、电话、地址,收件人姓名、电话、地址,还有订单编号和支付方式等。提供属性的访问和修改方法,方便对订单日期和相关人员信息进行管理 。
FreightCalculate 继承自抽象类 AbsCalculateFreight,主要职责是根据货物的重量等属性来计算运费费率和运费金额。在计算过程中,会结合客户类型进行不同的折扣计算,是运费计算业务逻辑的核心实现类 。
Order 继承自抽象类 AbsOrder,作用是整合订单的全量信息,包括航班、货物列表、订单日期信息、客户信息以及运费计算列表等。并通过相应方法展示客户详情与货物明细,是订单业务展示和管理的核心类 。
Main 作为程序的入口点,承担着从用户处获取输入数据的任务,然后基于这些数据创建各类的实例对象,并对业务流程进行组织和协调。例如,判断货物总重量是否超出航班载重限制等关键业务逻辑都在此类中实现 。

二、类间关键关系

  • 继承关系
    • FreightCalculate 类继承自 AbsCalculateFreight 抽象类,通过实现抽象类中定义的抽象方法,实现运费计算相关功能,体现了面向对象编程中代码复用和多态特性 。
    • Order 类继承自 AbsOrder抽象类,通过实现抽象类中定义的抽象方法,实现订单信息展示等功能,规范了订单类的行为 。
  • 组合关系
    • Order 与 Flight:一个 Order 包含一个 Flight 实例,表明订单与特定航班相关联,订单中的货物运输依赖该航班 。
    • Order与 Cargo:一个 Order 包含多个 Cargo 实例,说明一个订单中可能涉及多种货物 。
    • Order 与 OrderDate:一个 Order 包含一个 OrderDate 实例,用于记录订单的日期及收发件人等相关信息 。
    • Order 与 Customer:一个 Order 包含一个 Customer 实例,表明订单是由特定客户发起的 。
    • Order 与 FreightCalculate:一个 Order 包含多个 FreightCalculate 实例,因为一个订单中的多种货物需要分别计算运费 。

复杂度分析

1. 整体复杂度问题

  • 文件总行数 4.5K(4500行):这已经是一个超大型文件,说明我的代码 没有合理拆分模块,违反了 单一职责原则

  • 最大复杂度 8.15:某些方法(如 main)的圈复杂度较高(4),虽然不算灾难性,但仍有优化空间。

  • 平均方法复杂度 1.31:大部分方法比较简单,但存在 少数高复杂度方法(如 FreightCalculate.calculateFreight() 复杂度=3)。

2. 潜在设计问题

  • 6 个类挤在同一个文件:Java 最佳实践是 1 个类 = 1 个文件,我需要:

    • 将 CargoType、FreightCalculate 等拆分为独立 .java 文件

    • 使用包(package)组织代码

  • 注释率仅 0.2%:几乎没有注释,长期维护会非常困难,特别是:

    • AbsFreightCalculate 这种命名模糊的类

    • SPECIAL_CargoType() 等非常规方法

设计亮点与不足:

 设计亮点

  部分方法保持简洁

    • 如  FreightCalculate.calculateFreight() 的复杂度=1,说明简单逻辑封装得当。

    • 优势:符合 单一职责原则,易于测试和维护。

  面向对象的基础设计

    • 将运费计算(FreightCalculate)、货物类型(CargoType)等职责分离,没有全部塞进 main。

    • 优势:比纯面向过程的代码更易扩展。

主要不足

  巨型文件反模式

    • 问题:6 个类挤在 Main.java(4500 行),违反 单一职责原则

  几乎零注释

    • 问题:注释率仅 0.2%,关键方法(如运费计算逻辑)无说明。

    • 后果:后续开发者(包括我自己)需要反向推理业务逻辑。

心得:

  因为题目要求的改变,题目费率的计算方式变得很复杂,我最开始就是一种情况一个if_else判断导致我的复杂度很高,后来询问AI发现枚举 + Lambda可以避免了冗余的if-else,大大降低复杂度,逻辑集中、扩展性强。

3. 采坑心得

问题

  每次在题目的业务出现变动时,我的代码都会出现较大的改变,在一些类的设计上没有很好的可扩展性.

  我的商品重量一直算的实际重量,导致我题目一直部分正确.

  我的FreightCalculate.calculateFreight()最开始有if-else多层嵌套,最高复杂度达到了18,很需要修改.

  我的代码一点注释都没加.

心得

  我有许多问题是我以前就有的,甚至我写的时候也知道有这个问题,比如代码注释,但因为我认为反正这个比较简单就没在意,导致以后可能养成坏习惯.

4. 改进建议

  类的设计最开始要尽可能想全一点,要遵循设计原则,以免后续的业务增加或功能变动导致代码出现太大的变化,可扩展性要好,这两次题目集都有题目是在前一个题目的业务基础上增加其他功能改的,如果最开始类的设计合理就会变动很简单.

  对于题目的理解不能太基于自己的刻板印象,要尽可能的多思考有没有什么其他的可能,这样可以有效减少之后发现代码问题的难度,这次的重量计算就是很好的例子.

  在一个方法中不能有if-else多层嵌套,如果有很多中情况可以分成几个方法来处理,太多if-else嵌套会大大提高复杂度.

  代码注释应尽可能详细,便于之后的维护.

5. 总结

对类的设计原则有了更深的理解

  因为这两次的题目集有一些题是之前的题改了一下来的,让我认识到代码的可扩展性在实际设计中很重要,要遵循设计原则才能更好的维护代码.

对复杂度高的方法有了解决方法

  因为我的FreightCalculate.calculateFreight()最开始有if-else多层嵌套,最高复杂度达到了18,在网上查询后发现了一些,降低if-else多层嵌套的方法.

建议

学习引导强化

  每次题目集完成后,可考虑提供示例代码,并明确指出其中涉及的知识点。通过展示规范、合理的代码结构与实现方式,同学们能更直观地学习借鉴,快速掌握正确的编程思路与技巧。同时,清晰罗列所需知识,能让大家明确学习方向,进行针对性复习与拓展,有助于更全面、系统地掌握相关知识体系,提升编程能力与综合素养。
posted @ 2025-05-23 11:19  落羽无痕  阅读(8)  评论(0)    收藏  举报