第二次blog作业题目集8~9

前言
相比于电梯调度程序需处理多线程协调、复杂状态流转与算法优化的高难度挑战,近期题目集更聚焦于面向对象编程的基础能力训练。其难度梯度更侧重类的设计方法论,例如如何通过合理抽象定义父类与子类的层次结构,精准封装类的属性与行为,以及运用继承、多态等特性实现代码复用。这种设计更注重考察“类的职责划分”“接口定义的合理性”等基础能力,适合系统强化面向对象设计的规范意识,帮助开发者建立从“数据与行为封装”到“模块间关系构建”的完整编程思维链路。
设计与分析
题目集8
类图设计如下

对类图的分析:

Cargo 类:
作用:用于封装货物相关信息,是货物数据的载体。
属性

  • name:货物名称,字符串类型,用于标识货物。
  • cargoID:货物编号,字符串类型,唯一识别货物。
  • weight:货物重量,双精度浮点型,记录货物重量数值。
  • length:货物长度,双精度浮点型。
  • width:货物宽度,双精度浮点型。
  • height:货物高度,双精度浮点型。

方法:包含属性对应的 Getter 和 Setter 方法,用于获取和设置属性值;还有两个构造函数,一个无参构造用于创建默认对象,另一个带参构造用于在创建对象时初始化属性。

Flight 类:
作用:用于管理航班信息,是航班数据的存储和操作单元。
属性

  • flightID:航班编号,字符串类型,用于唯一标识航班。
  • firstAirport:起始机场,字符串类型。
  • lastAirport:目的地机场,字符串类型。
  • date:航班日期,字符串类型。
  • maxWeight:航班最大载重,整型。

方法:包含属性对应的 Getter 和 Setter 方法,用于获取和修改属性值;有两个构造函数,一个无参,一个带参,带参构造可在创建对象时初始化属性。

Order 类:
作用:用于处理订单相关业务,是订单数据的封装体。
属性

  • orderDate:订单日期,字符串类型。
  • orderID:订单编号,字符串类型,唯一标识订单。

方法:包含属性对应的 Getter 和 Setter 方法,用于获取和设置属性值;有两个构造函数,一个无参,一个带参,带参构造用于初始化属性。

Passenger 类:
作用:用于存储和管理乘客信息,是乘客数据的载体。
属性

  • name:乘客姓名,字符串类型。
  • ID:乘客身份证号,字符串类型。
  • address:乘客地址,字符串类型。

方法:包含属性对应的 Getter 和 Setter 方法,用于获取和设置属性值;有两个构造函数,一个无参,一个带参,带参构造用于初始化属性。

Agent 类:
作用:作为业务核心协调类,整合各类业务信息,协调货物运输、航班安排、订单处理、乘客服务等业务流程。
属性

  • cargoList:货物列表,类型为LinkedList,用于存储多个货物对象。
  • flight:航班对象,类型为Flight,关联航班信息。
  • passenger:乘客对象,类型为Passenger,关联乘客信息。
  • sender:发货人对象,类型为Sender,关联发货人信息。
  • receiver:收货人对象,类型为Receiver,关联收货人信息。
  • order:订单对象,类型为Order,关联订单信息。
  • rate:费率计算器对象,类型为RateCalculator,用于计算费用相关。
  • totalWeight:总重量,双精度浮点型,记录货物总重等。
  • totalPay:总费用,双精度浮点型,记录业务总费用。

方法:包含属性对应的 Getter 和 Setter 方法,用于获取和设置属性值;有两个构造函数,用于初始化对象属性;还有一些业务相关方法,如获取总费用、货物列表等。

Sender 类:
作用:代表发货人角色,用于存储和管理发货人信息,可进行发货人相关业务操作。
属性

  • name:发货人姓名,字符串类型。
  • address:发货人地址,字符串类型。
  • tele:发货人电话,字符串类型。

方法:包含属性对应的 Getter 和 Setter 方法;继承自printInfos抽象类,需实现printInfo()方法,用于打印发货人信息;有两个构造函数,用于对象创建时的属性初始化。

Receiver 类:
作用:代表收货人角色,用于存储和管理收货人信息,可进行收货人相关业务操作。
属性

  • name:收货人姓名,字符串类型。
  • address:收货人地址,字符串类型。
  • tele:收货人电话,字符串类型。

方法:包含属性对应的 Getter 和 Setter 方法;继承自printInfos抽象类,需实现printInfo()方法,用于打印收货人信息;有两个构造函数,用于对象创建时的属性初始化。

printInfos 类:
作用:抽象类,为 Sender 和 Receiver 提供统一的信息打印规范,通过定义抽象方法printInfo(),实现代码的抽象和复用。

方法:抽象方法printInfo(),要求子类必须实现,用于打印相关信息。

RateCalculator 类:
作用:专注于费率计算业务,为货物运输等业务提供费用计算功能。

方法:calculateRate()方法,用于计算费率,返回双精度浮点型的费率值。

源码分析
air.java 代码不足分析
(除了Main类其他类都放在air.java文件里)

  • 代码行数与语句数量:air.java 有 404 行,233 条语句 ,代码量相对较多,存在结构不够紧凑、功能拆分不够细致的问题,导致代码冗余。

  • 分支语句占比:分支语句占比仅 4.7% ,意味着代码逻辑相对简单直接,说明一些复杂逻辑没有通过合理的分支结构处理,存在代码逻辑不完整或不够灵活的风险。

  • 方法调用语句数量:方法调用语句 18 条,数量不算多,反映出代码中方法间的协作不够充分,功能内聚性可能欠佳,或者存在一些功能重复实现而未提取成方法调用的情况。

  • 注释行占比:注释行占比仅 3.2% ,注释过少,不利于代码的理解和维护,其他开发人员很难快速了解代码的功能和逻辑。

  • 类和接口数量:有 8 个类和接口,平均每个类 8.88 个方法 ,类的职责可能不够单一,一个类承担了过多功能,导致方法数量较多,增加了代码理解和维护难度。

  • 方法复杂度:RateCalculator.calculaterRate() 方法复杂度为 5,是最复杂的方法,可能内部逻辑混乱,可读性差,且不易于修改和扩展。其他一些方法也有一定复杂度,说明代码整体方法复杂度控制不佳。

  • 代码块深度:最大代码块深度为 3,平均代码块深度 1.49 ,虽然整体深度不算特别高,但存在深度为 3 的代码块,可能存在一定程度的逻辑嵌套,影响代码清晰度。

Main.java 代码不足分析

  • 代码行数与语句数量:Main.java 有 68 行,50 条语句 ,在代码行数较少的情况下语句数相对较多,存在代码不够简洁的问题。

  • 分支语句占比:分支语句占比 6.0% ,不算高,代码逻辑处理不够丰富,对于复杂业务场景的应对能力不足。

  • 方法调用语句数量:14 条方法调用语句,可能方法间的调用关系不够合理,存在重复调用或调用层次混乱的潜在问题。

  • 注释行占比:注释行占比 36.8% ,虽然注释比例看似较高,但可能存在注释质量不高的情况,比如注释没有准确解释关键逻辑等。

  • 方法复杂度:Main.main() 方法复杂度为 4,复杂度较高,内部逻辑可能较为复杂,不易于理解和调试。

  • 代码块深度:最大代码块深度为 4,平均代码块深度 2.78 ,代码块深度较高,存在较多嵌套逻辑,使得代码逻辑理解难度增大。

题目集9
类图设计如下

** Agent类**

  • 作用:作为业务核心协调类,整合各类业务信息,协调货物运输、航班安排、订单处理、乘客服务等业务流程,是整个业务逻辑的控制和管理中心。
  • 属性:包含cargolist(货物列表)、flight(航班对象)、passenger(乘客对象)、order(订单对象)、sender(发货人对象)、receiver(收货人对象)、rate(费率计算器对象)等 ,涵盖了业务涉及的主要实体信息。
  • 方法:有多个属性的Getter和Setter方法,用于获取和设置属性值;还有业务相关方法,如获取总重量、总费用等,用于处理业务逻辑。

Cargo类

  • 作用:货物的抽象基类,定义货物的通用属性和行为,是所有具体货物类型的父类。
  • 属性:包括name(名称)、type(类型)、weight(重量)、length(长度)、width(宽度)、height(高度)等 ,用于描述货物基本特征。
  • 方法:包含属性对应的Getter和Setter方法;还有构造函数用于对象初始化;以及calculateVolume(计算体积)等通用业务方法。

ExpressCargo类

  • 作用:继承自Cargo类,代表快递货物,在Cargo类基础上可能扩展快递相关特性。
  • 属性:继承Cargo类属性,可能添加如快递单号、快递优先级等特有属性(图中未显示,推测)。
  • 方法:继承Cargo类方法,可重写父类方法以适应快递业务需求,也可能新增快递业务相关方法。

** DangerousCargo类**

  • 作用:继承自Cargo类,代表危险货物,在Cargo类基础上增加危险货物相关属性和行为。
  • 属性:继承Cargo类属性,可能有危险等级、危险类别、安全处理说明等特有属性(图中未显示,推测)。
  • 方法:继承Cargo类方法,可重写部分方法以满足危险货物管理要求,也可能新增危险货物运输、存储等相关方法。

** RegularCargo类**

  • 作用:继承自Cargo类,代表普通货物,具备Cargo类的基本属性和方法。
  • 属性:继承Cargo类属性,无特殊新增属性(图中未显示,推测)。
  • 方法:继承Cargo类方法,可根据普通货物业务需求重写部分方法。

Flight类

  • 作用:用于管理航班信息,是航班数据的存储和操作单元。
  • 属性:包含flightID(航班编号)、firstAirport(起始机场)、lastAirport(目的地机场)、date(日期)、maxWeight(最大载重)等 ,用于标识和描述航班。
  • 方法:包含属性对应的Getter和Setter方法;构造函数用于初始化航班对象;还有与航班业务相关方法,如判断是否超重等。

Order类

  • 作用:用于处理订单相关业务,是订单数据的封装体。
  • 属性:有orderDate(订单日期)、orderID(订单编号)等 ,用于标识和记录订单信息。
  • 方法:包含属性对应的Getter和Setter方法;构造函数用于创建订单对象;可能有订单状态查询、订单费用计算等相关方法。

** Passenger类**

  • 作用:用于存储和管理乘客信息,是乘客数据的载体。
  • 属性:包含name(姓名)、ID(身份证号)、address(地址)等 ,用于记录乘客基本信息。
  • 方法:包含属性对应的Getter和Setter方法;构造函数用于创建乘客对象;可能有乘客登机手续办理等相关方法。

Sender类

  • 作用:代表发货人角色,用于存储和管理发货人信息,可进行发货人相关业务操作。
  • 属性:继承自InfoPerson类,有name(姓名)、address(地址)、tele(电话)等 ,用于标识发货人。
  • 方法:继承InfoPerson类的printInfo方法,用于打印发货人信息;还有属性对应的Getter和Setter方法;可能有发货单创建等业务方法。

** Receiver类**

  • 作用:代表收货人角色,用于存储和管理收货人信息,可进行收货人相关业务操作。
  • 属性:继承自InfoPerson类,有name(姓名)、address(地址)、tele(电话)等 ,用于标识收货人。
  • 方法:继承InfoPerson类的printInfo方法,用于打印收货人信息;还有属性对应的Getter和Setter方法;可能有收货确认等业务方法。

** InfoPerson类**

  • 作用:作为抽象类,为Sender和Receiver提供统一的信息打印规范,通过定义抽象方法printInfo,实现代码的抽象和复用。
  • 属性:无。
  • 方法:抽象方法printInfo,要求子类必须实现,用于打印相关信息。

RateCalculator类

  • 作用:专注于费率计算业务,为货物运输等业务提供费用计算功能。
  • 属性:无。
  • 方法:calculaterRate方法,用于计算费率,返回费率值,是业务费用计算的核心方法。

源码分析

Main.java 代码问题分析

  • 代码行数与语句数量:Main.java 有78行,59条语句 ,代码行数和语句数不算多,但平均每条语句占比相对较高,可能存在代码不够简洁的情况。

  • 分支语句占比:分支语句占比10.2% ,说明代码中存在一定条件判断逻辑,但占比不算高,可能对于复杂业务场景的逻辑处理不够全面。

  • 方法调用语句数量:19条方法调用语句,数量适中,但如果方法调用层次不清晰,可能导致代码逻辑难以理解。

  • 注释行占比:注释行占比32.1% ,注释比例相对较高,但需关注注释是否准确解释代码逻辑,否则可能存在注释无效或误导的问题。

  • 方法复杂度:Main.main()`方法复杂度为7,复杂度较高,内部逻辑可能较为复杂,包含较多条件判断、循环等逻辑结构,不易于理解和调试。

  • 代码块深度:最大代码块深度为4,平均代码块深度2.80 ,代码块深度较高,存在较多嵌套逻辑,使得代码逻辑理解难度增大。

  • aviation.java 代码问题分析

  • 代码行数与语句数量:aviation.java`有494行,208条语句 ,代码行数较多,语句数相对代码行数不算高,可能存在代码结构松散、冗余的问题。

  • 分支语句占比:分支语句占比11.1% ,存在一定分支逻辑,但占比不算高,可能对于复杂业务场景处理能力有限。

  • 方法调用语句数量:14条方法调用语句,数量不算多,可能方法间协作不够充分,存在功能内聚性欠佳的问题。

  • 注释行占比:注释行占比仅4.7% ,注释过少,不利于代码的理解和维护,其他开发人员很难快速了解代码功能和逻辑。

  • 类和接口数量:有11个类和接口,平均每个类9.91个方法 ,类的职责可能不够单一,一个类承担了过多功能,导致方法数量较多,增加了代码理解和维护难度。

  • 代码块深度:最大代码块深度为3,平均代码块深度1.50 ,虽然整体深度不算特别高,但存在深度为3的代码块,可能存在一定程度的逻辑嵌套,影响代码清晰度。

踩坑心得
在题目集08里,一开始总是出现非零返回

仔细检查后发现是因为getRate()方法的返回类型被写为int而不能用%。1f进行输出;

修改之后异常测试仍然过不去,检查后发现在语句中间少了一个空格,以后直接复制异常测试的输出语句更不容易出错;

在题目集09中
还是存在非零返回的问题

检查后发现是在读取数据时漏写了读取支付方式的语句,导致预计输入与实际输入类型不符

编译器输出了很多重复的问题,检查后发现是RegularCargo的构造方法里忘了加修饰词,直接从另一个子类复制过来了没有仔细看

改进建议

  • 注意对格式化字符串的检查
  • 在关键输入、输出操作处添加异常处理,帮助我们发现问题
  • 在关键部分添加注释,增强代码的可读性
  • Main方法的职责不少,可以进行更细致的拆分,例如可以把业务逻辑拆分出来
  • 在输入数据前可以用hasNext()进行验证

总结
通过这两次题目集,我学习到了利用抽象类和继承实现复用,如Information接口规范信息打印行为。输入处理中,用Scanner的hasNext()验证类型,结合循环处理非法输入,避免InputMismatchException,并通过try-catch捕获异常(如格式化错误),代码可读性方面,添加类、方法注释说明逻辑(如Cargo计费规则),使用清晰变量名。数据模型需封装属性,通过公共方法暴露功能,如Cargo计算计费重量。注重格式化字符串与参数类型匹配,防止类型异常,同时通过测试覆盖边界情况,提升代码健壮性与可维护性。

posted @ 2025-05-24 17:41  今天收到roy6了吗  阅读(24)  评论(0)    收藏  举报