面向对象程序设计-第二阶段汇报总结-航空航空货运管理系统
面向对象程序设计-第二阶段汇报总结-航空航空货运管理系统
前言
本次航空空运系统开发阶段历时两周,每周聚焦一个小阶段任务,难度呈阶梯式递增,逐步推进系统的完善与升级。在前期设计基础上,围绕继承机制展开类的架构设计,将不同类型的航班、货物运输等功能分类封装,使各模块遵循单一职责原则,让系统结构更清晰;后期难度进一步提升,考验代码的可扩展性,借助多态特性实现系统的灵活迭代,使系统能够轻松应对不同运输场景与业务需求的变化。在第一阶段的探索中,航空空运系统庞大复杂的业务逻辑犹如浩瀚云海,令人望而生畏,不知道该怎么设计好类图,何时应该使用继承,何时应该使用聚集,这都在本阶段中得以锻炼,随着对继承与多态概念的深入理解与运用,后续的迭代开发逐渐变得顺畅;在第二阶段的系统扩展中,通过第一次代码继承迭代的合理性,使得扩展更加容易,代码更灵活,这一过程让我明白,一个高效稳定的航空空运系统,绝非一蹴而就,而是需要借助继承与多态等面向对象特性,分阶段、有层次地逐步实现。
设计与分析
第一次作业分析:
航空货运管理系统(类设计):
本次题目模拟某客户到该航空公司办理一次货运业务的过程:
航空公司提供如下信息:
航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班
日期,航班最大载重量)
客户填写货运订单并进行支付,需要提供如下信息:
- 客户信息(姓名,电话号码等)
- 货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
- 运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选
航班号,订单日期) - 支付方式(支付宝支付、微信支付)
注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独
计费。
- 程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信息报表及货物明细报表。
- 本次题目重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开闭原则以及合成复用原则。
输入格式:
客户编号
客户姓名
客户电话
客户地址
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话
输出格式:
- 如果订单中货物重量超过航班剩余载重量,程序输出
The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order.程序终止运行。 - 如果航班载重量可以承接该订单,输出如下:
客户:姓名(电话)订单信息如下:
航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
微信支付金额:
货物明细如下:
明细编号 货物名称 计费重量 计费费率 应交运费
1 ...
2 ...
题目分析:
本题围绕航空货运管理系统的空运费计算展开,综合考察多项面向对象设计原则。题目要求从键盘获取航班、客户、货物、运送及支付方式等多元信息,构建能处理多件货物独立计费的货运订单系统,并生成订单与货物明细报表。刚开始分析题目设计类图时,只考虑订单类,后经不断对类图进行优化,综合考虑单一职责原则,增加订单明细类,其解题关键在于依据单一职责原则拆分各功能模块,利用里氏代换原则保障子类对父类的行为兼容,遵循开闭原则实现系统功能扩展的灵活性,通过合成复用原则提升代码复用性。
类图设计:

核心类及关系
- Main类:程序入口,调用Constructor类创建订单等操作,通过Scanner获取输入。
- Constructor类:负责订单构建,有多个构造方法,可创建Order对象并执行订单相关操作。
- Order类:订单核心类,包含订单编号、日期等信息,关联乘客、寄件人、收件人、航班、支付方式及货物明细(LinkedList
)等,有增删货物明细、计算总费用和总重量等方法。 - People类:人员抽象类,有姓名、电话等属性及对应访问器方法,被Passenger(乘客)、Sender(寄件人)、Recipient(收件人)继承。
- Flight类:航班类,记录航班编号、起降地、日期、最大载重量等信息。
- Payment类:支付抽象类,有支付方法,WechatPay(微信支付)是其子类。
- Ordercargo类:订单货物关联类,关联订单和货物,有设置货物及费率、计算费用等方法。
- Cargo类:货物类,记录货物编号、名称、长宽高等信息,有对应访问器方法。
设计原则体现
- 单一职责原则:各功能分散在不同类中,如Order类负责订单整体管理,Cargo类负责货物信息管理,功能职责明确。
- 里氏代换原则:Passenger、Sender、Recipient继承自People,可在程序中以People类型统一处理,满足里氏代换原则。
- 开闭原则:新增支付方式(如支付宝支付)等功能时,可通过继承Payment类实现,不修改现有支付类代码,满足开闭原则。
- 合成复用原则:类间通过组合关联,如Order类组合People、Flight、Payment等类对象实现功能复用。
- 依赖倒转原则:高层模块不依赖底层模块(如Payment具体子类)的实现细节,依赖抽象(Payment抽象类),降低耦合度。
SourceMonitor分析:

从 Kiviat Graph 指数来看,类均方法数适中,在类和方法功能划分上有初步模块化基础。但存在方法复杂度不均,部分方法复杂度较高,且逻辑嵌套较深,方法平均语句数可能冗余等缺陷。后续可通过重构复杂方法、优化逻辑嵌套以及完善注释等方式进行改进,审查方法内语句,去除冗余代码,提高代码简洁性和可读性。
第二次作业分析:
航空货运管理系统(继承与多态):
本次题目模拟某客户到该航空公司办理一次货运业务的过程:
在上一次作业的基础上扩展:
1.货物类型分为普通货物、危险货物和加急货物三种,费率都不相同
2.增加现金支付
3.计算公式:基础运费 = 计费重量 × 费率 × 折扣率
用户分为个人用户和集团用户,其中个人用户可享受订单运费的9折优惠,集团用户可享受订单运费的8折优惠
航空公司提供如下信息:
航班信息(航班号,航班起飞机场所在城市,航班降落机场所在城市,航班
日期,航班最大载重量)
客户填写货运订单并进行支付,需要提供如下信息:
- 客户信息(姓名,电话号码等)
- 货物信息(货物名称,货物包装长、宽、高尺寸,货物重量等)
- 运送信息(发件人姓名、电话、地址,收件人姓名、电话、地址,所选
航班号,订单日期) - 支付方式(支付宝支付、微信支付、现金支付)
注:一个货运订单可以运送多件货物,每件货物均需要根据重量及费率单独
计费。
- 程序需要从键盘依次输入填写订单需要提供的信息,然后分别生成订单信息报表及货物明细报表。
- 本次题目重点考核面向对象设计原则中的单一职责原则、里氏代换原则、开闭原则以及合成复用原则、依赖倒转原则。
输入格式:
客户类型[可输入项:Individual/Corporate]
客户编号
客户姓名
客户电话
客户地址
货物类型[可输入项:Normal/Expedite/Dangerous]
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话
支付方式[可输入项:Wechat/ALiPay/Cash]
输出格式:
- 如果订单中货物重量超过航班剩余载重量,程序输出
The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order.程序终止运行。 - 如果航班载重量可以承接该订单,输出如下:
客户:姓名(电话)订单信息如下:
航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
微信支付金额:
货物明细如下:
明细编号 货物名称 计费重量 计费费率 应交运费
1 ...
2 ...
题目分析:
本题围绕航空货运管理系统的空运费计算展开,在原有基础上进行了扩展。计算方面,明确计费重量取实际重量与体积重量较高者,基础运费计算考虑货物类型(普通、危险、加急)对应的不同费率,还引入用户类型(个人、集团)对应的折扣率。 业务流程模拟客户办理货运业务,需从键盘输入航班、客户、货物、运送及支付方式等信息,生成订单及货物明细报表。有了前一次类设计的基础,使得本次作业扩展较为灵活,能很快达到扩展目的。这也让我深刻意识到面向对象设计原则的重要性。
类图设计:

核心类及职责
- Cargo类:表示货物,有编号、名称、长宽高等属性及访问方法,按货物类型(普通、加急、危险)细分,各有折扣率属性。
- Payment类:支付抽象类,有支付方法,WechatPay(微信支付)、Alipay(支付宝支付)、Cash(现金支付)为其子类。
- Passenger类:继承自People,增加 ID、类型属性及设置方法,按用户类型分为Individual(个人用户)、Corporate(集团用户),各有折扣率属性。
- 其他类与上次作业相同。
设计原则体现
与上次作业一致实现基本设计原则,并因为有了之前良好的类设计基础,代码的灵活度高,在不改变现有代码的情况下(如支付类),实现功能的扩展,各功能职责明确,耦合度低。
SourceMonitor分析:

从 Kiviat Graph 指数来看,代码在类的划分上有一定的合理性,不同类负责相对独立的功能,初步具备模块化的特征。但存在较为复杂的方法,相比于上一次作业来看Max Complexity指数增大了,后续应尽可能减少嵌套语句等复杂方法使用,尽量使得方法简单,提高代码的简洁性和可读性。
踩坑心得
- 前期类设计中并未将支付类单独成类,导致在后续无法再扩展其他支付方式,可见继承与多态的重要性。
- 刚开始做类设计时,只考虑到订单类和货物类,这使得代码耦合度较高,在检查问题时并不能很清楚的找到哪里出现了问题,使得刚开始调度算法逻辑较为困难,可见,一个良好的类设计对于整个项目的顺利推进和后期维护至关重要,它能够使代码结构更加清晰,降低开发和维护的难度。
- 之后再次对类设计进行优化,进一步减小耦合,保证单一职责原则。在订单类中,不仅包含了订单的基本信息,还将所有货物的详细信息和操作都集中处理,却没有设计订单明细类来专门管理货物的详细信息,这使得订单类的职责过多,代码的耦合度高,设计原则并未较好的体现,代码的可扩展性和可读性较低。
- 在订单类中计算总重量时,理应计算的是体积重量,而在第一次计算中我使用的是实际重量,导致虽然所给示例正确,但实则内部算法逻辑存在问题。这一问题的出现,也让我更加深刻地认识到在代码实现过程中,必须严格按照业务需求进行逻辑设计,不能仅仅满足于示例数据的正确输出,要确保代码逻辑在各种实际场景下都能准确无误地运行 。
修改前代码:
点击查看代码
public double gettotalweight() {
double total=0;
for(int i=0;i<cargos.size();i++)
total=total+cargos.get(i).getCargo().getWeight();
return total;
}
修改后代码:
点击查看代码
public double gettotalweight() {
double total=0;
for(int i=0;i<cargos.size();i++)
total=total+cargos.get(i).getCargo().getChargeweight();
return total;
}
改进建议
- 在编写代码时,遵循单一职责原则并将代码模块化是保障程序质量的重要基石。单一职责原则强调每个模块、类或函数都应当仅有一个引起它变化的原因,即只负责一项明确的功能。设计专门的订单明细类,将货物的详细信息和操作转移到该类中。
- 在每次类设计和代码实现后,进行代码审查,检查类设计是否遵循设计原则,代码逻辑是否符合业务需求,是否存在潜在的耦合问题等。同时,制定全面的测试计划,包括单元测试、集成测试和功能测试等,覆盖各种业务场景和边界条件,及时发现并解决代码中存在的问题,确保代码质量。
- 类设计是软件开发的底层骨架,它的质量直接关乎项目的成败。合理的类设计遵循单一职责、低耦合高内聚等原则,将复杂系统拆解为功能明确、边界清晰的模块,使代码逻辑一目了然,大幅提升可读性与可维护性。
- 弄清继承和聚集的区别,当类之间为is-a的关系时才使用继承,否则会使得代码的耦合度较高,不易扩展与维护。
- 提升自己的社交能力和团队协作能力,一个人的力量是狭小的,如果只靠一个人的能力是很难解决一整个问题的,在这次阶段性作业中我意识到了交流的重要性,在互相借鉴的交流中我们能了解到更多不同的思维方式,这样也能避免自己花费大量走弯路。
总结
经过本阶段围绕航空空运系统的实践,我对课程知识有了更为深刻的领悟。在这一过程中,继承与多态的概念不再只是书本上的理论,而是成为构建高效系统的有力工具。继承让我能够创建类的层次结构,例如在货物类的设计中,普通货物、危险货物和加急货物类继承自通用货物类,复用其基础属性与方法,同时根据自身特性进行扩展,极大地提高了代码的复用性。多态则赋予了程序灵活性,不同类型的货物在计算运费等操作时,虽调用相同的方法名,但依据自身类型执行不同的逻辑,使系统能够轻松应对多样化的业务需求。在后续学习中,我会保持积极的学习态度,不断钻研,提升自己在开发以及面向对象编程方面的能力。

浙公网安备 33010602011771号