第二次作业BLOG
一、前言
这次blog所总结的8,9次pta大作业难度比以前几次要好一点,主要是不用再思考像电梯问题那样令人奔溃的算法了,但是还是具有一定的难度,主要问题在继承,多态,数组和类设计方面。这两次关于航空货运的管理系统,关于相关的设计还是需要好多的思考,因为要自己先设计类图,再进行代码实现。特别是我们上课讲到的面向对象七大原则,里氏代换,单一职责啥的,平常在课上很好理解,但是在实践方面用到还是要花点功夫。前面的小题基本上都是我们前几次作业的迭代,只需要加入继承,接口,就差不多完成了。总的来说完成的时间要快一点点,没有发生和以前电梯一样花上一整周的情况(其实这都差点没做完)。
二、设计与分析
第八次作业第三题:
航空快递以速度快、安全性高成为急件或贵重物品的首选。本题目要求对航空货运管理系统进行类设计,具体说明参看说明文件。
输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息
客户编号
客户姓名
客户电话
客户地址
运送货物数量
[货物编号
货物名称
货物宽度
货物长度
货物高度
货物重量
]//[]内的内容输入次数取决于“运送货物数量”,输入不包含“[]”
航班号
航班起飞机场
航班降落机场
航班日期(格式为YYYY-MM-DD)
航班最大载重量
订单编号
订单日期(格式为YYYY-MM-DD)
发件人地址
发件人姓名
发件人电话
收件人地址
收件人姓名
收件人电话
输出格式:
如果订单中货物重量超过航班剩余载重量,程序输出The flight with flight number:航班号 has exceeded its load capacity and cannot carry the order. ,程序终止运行。
如果航班载重量可以承接该订单,输出如下:
客户:姓名(电话)订单信息如下:
航班号:
订单号:
订单日期:
发件人姓名:
发件人电话:
发件人地址:
收件人姓名:
收件人电话:
收件人地址:
订单总重量(kg):
微信支付金额:
货物明细如下:
明细编号 货物名称 计费重量 计费费率 应交运费
1 ...
2 ...
注:输出中实型数均保留1位小数。
程序类图:

代码分析图:
![]()
Metrics Details For File 'Main.java'
Parameter Value
========= =====
Project Directory C:\Users\32306\IdeaProjects\untitled13\src
Project Name
Checkpoint Name Baseline
File Name Main.java
Lines 217
Statements 169
Percent Branch Statements 4.7
Method Call Statements 14
Percent Lines with Comments 0.0
Classes and Interfaces 9
Methods per Class 8.33
Average Statements per Method 1.43
Line Number of Most Complex Method 62
Name of Most Complex Method DefaultRate.getMax()
Maximum Complexity 5
Line Number of Deepest Block 74
Maximum Block Depth 3
Average Block Depth 1.69
Average Complexity 1.50
Most Complex Methods in 7 Class(es): Complexity, Statements, Max Depth, Calls
Customer.Customer() 1, 4, 2, 0
Customer.getName() 1, 1, 2, 0
Customer.getPhone() 1, 1, 2, 0
DefaultRate.getMax() 5, 8, 3, 0
Flight.Flight() 1, 5, 2, 0
Flight.getMax() 1, 1, 2, 0
Flight.getNumber() 1, 1, 2, 0
goods.getgWeight() 1, 1, 2, 0
goods.getName() 1, 1, 2, 0
goods.goods() 1, 8, 2, 1
Main.getMax() 3, 37, 3, 9
Order.getMax() 2, 17, 3, 4
Order.getMax() 1, 1, 2, 0
Order.getMax() 2, 6, 3, 0
Order.getMax() 1, 14, 2, 0
WeChatPayment.getMax() 1, 1, 2, 0
Block Depth Statements
0 10
1 52
2 87
3 20
4 0
5 0
6 0
7 0
8 0
9+ 0
解释:这次问题类设计比较复杂,而且里面还有分段计费,多种支付方法,很显著的用到了继承和多态,这样就运用到了里氏代换原则和依赖倒转原则,还设计了航班,顾客,订单类等,运用到了单一职责原则和迪米特法则。
心得:第一次将这么多法则都运用到这个复杂问题中,更加体现出来了在写代码之前进行设计和把类图画出来的重要性,如果直接一股脑开始写,也许能够写出来通过测试的代码,但是很难符合设计要求。
第九次作业第三题
航空快递以速度快、安全性高成为急件或贵重物品的首选。本题目要求对航空货运管理系统进行类设计,具体说明参看说明文件。
输入格式:
按如下顺序分别输入客户信息、货物信息、航班信息以及订单信息。
客户类型[可输入项: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 ...
注:输出中实型数均保留1位小数。
类图设计:

代码分析:

Metrics Details For File 'Main.java'
Parameter Value
========= =====
Project Directory C:\Users\32306\IdeaProjects\untitled13\src
Project Name
Checkpoint Name Baseline
File Name Main.java
Lines 314
Statements 121
Percent Branch Statements 14.9
Method Call Statements 9
Percent Lines with Comments 0.0
Classes and Interfaces 12
Methods per Class 2.67
Average Statements per Method 2.09
Line Number of Most Complex Method 72
Name of Most Complex Method ExpediteRate.getRate()
Maximum Complexity 5
Line Number of Deepest Block 60
Maximum Block Depth 3
Average Block Depth 1.60
Average Complexity 2.13
Most Complex Methods in 9 Class(es): Complexity, Statements, Max Depth, Calls
chooseRate.getRate() 5, 10, 3, 3
Company.Company() 1, 1, 2, 1
Company.getDiscountRate() 1, 1, 2, 0
Customer.Customer() 1, 4, 2, 0
Customer.getName() 1, 1, 2, 0
Customer.getPhone() 1, 1, 2, 0
DangerousRate.getRate() 5, 8, 3, 0
ExpediteRate.getRate() 5, 8, 3, 0
Goods.getGWeight() 1, 1, 2, 0
Goods.getName() 1, 1, 2, 0
Goods.getRate() 1, 1, 2, 0
Goods.Goods() 3, 13, 3, 1
NormalRate.getRate() 5, 8, 3, 0
person.getDiscountRate() 1, 1, 2, 0
person.person() 1, 1, 2, 1
WeChatPay.getRate() 1, 1, 2, 0
Block Depth Statements
0 13
1 41
2 49
3 18
4 0
5 0
6 0
7 0
8 0
9+ 0
解释:这次作业比上一次增加了个人会员和团体会员两个选项有不同的优惠程度,还增加了不同的货物对应的运输费收取的比例不同,而且上次的支付方式选择在测试中并没有用到,这次用到了,这些增加的改变让继承和多态更加深入的使用到了,这也更多的使用到了里氏代换和依赖倒转,而且增加新功能也让开闭原则淋漓尽致的体现出来了,如果在第一次的设计中符合开闭原则,那麽这次作业就很简单了(可惜我并没有做到)。
心得:有了上一次的经验,这次作业完成的容易多了,但是还是有一些地方不够完美,比如输入有时候匹配不上,不同货物的识别有时候对不上,但是在修改几次之后还是通过了测试用例。后来才知道工厂模式可以很容易的完成这个多态的实现,可惜当时不会。
三、踩坑心得:
1.一定要看好题目的要求再编写代码,最开始有一次输入的要求看的不仔细,写Sestem.in的时候少写了一个,一直输入后编译错误,这只是个小错误,要是做更复杂的问题的情况下看错了问题就很大了,一定要记住!!!
点击查看代码
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String customerType = scanner.nextLine();
String customerId = scanner.nextLine();
String customerName = scanner.nextLine();
String customerPhone = scanner.nextLine();
String customerAddress = scanner.nextLine();
Customer customer;
if ("Individual".equals(customerType)) {
customer = new person(customerId, customerName, customerPhone, customerAddress);
} else {
customer = new Company(customerId, customerName, customerPhone, customerAddress);
}
String goodsType = scanner.nextLine();
int goodsCount = Integer.parseInt(scanner.nextLine());
List<Goods> goodsList = new ArrayList<>();
for (int i = 1; i <= goodsCount; i++) {
String id = scanner.nextLine();
String name = scanner.nextLine();
double width = Double.parseDouble(scanner.nextLine());
double length = Double.parseDouble(scanner.nextLine());
double height = Double.parseDouble(scanner.nextLine());
double weight = Double.parseDouble(scanner.nextLine());
goodsList.add(new Goods(id, name, width, length, height, weight, goodsType));
}
String flightNumber = scanner.nextLine();
String departure = scanner.nextLine();
String arrival = scanner.nextLine();
String flightDate = scanner.nextLine();
double maxLoad = Double.parseDouble(scanner.nextLine());
Flight flight = new Flight(flightNumber, departure, arrival, flightDate, maxLoad);
String orderId = scanner.nextLine();
String orderDate = scanner.nextLine();
String senderAddress = scanner.nextLine();
String senderName = scanner.nextLine();
String senderPhone = scanner.nextLine();
String receiverAddress = scanner.nextLine();
String receiverName = scanner.nextLine();
String receiverPhone = scanner.nextLine();
String paymentMethod = scanner.nextLine();
2.一定要遵守里氏代换原则,第一次作业我发现测试用例里面支付方法只有WeChatpay,就直接把实现方法写到WeChat里面了,第二次迭代的时候忘记了,发现怎么写都是微信支付,后来才发现,这样改起来很麻烦,也不符合开闭原则。
点击查看代码
interface Payment {
String getName();
}
class WeChatPay implements Payment {
@Override
public String getName() {
return "微信支付";
}
}
class AliPayPay implements Payment {
@Override
public String getName() {
return "支付宝支付";
}
}
class money implements Payment {
@Override
public String getName() {
return "现金支付";
}
}
四、改进意见:
1.写代码要带注释
这次和上一次一样,代码的注释率还是0,而且这两次作业的关联更大,加上注释能让迭代更加简单,主要是重点给复杂的代码、循环、判断还有自己写的方法加注释,说说代码干啥用、为啥这么写。有了注释,以后复习、改 bug 都能省不少事儿。不然等到迭代的时候看都看不懂,就真是竹篮打水一场空了。
2.可以使用工厂模式直接对不同的输入进行选择。
工厂方法模式定义了一个创建对象的接口,但由子类决定实例化哪个类。 工厂方法将对象的创建延迟到子类。这是这次作业结束之后在课上讲的,但是在这次作业上非常合适,个人会员和集体会员,不同货物的收费,以及支付方法都可以使用。
点击查看代码
class chooseRate {
public static Rate getRate(String rateType) {
Rate rate;
if ("Normal".equals(rateType)) {
rate = new NormalRate();
} else if ("Expedite".equals(rateType)) {
rate = new ExpediteRate();
} else if ("Dangerous".equals(rateType)) {
rate = new DangerousRate();
} else {
throw new IllegalArgumentException(rateType);
}
return rate;
}
}
3.一定要为程序以后的改进做好准备
也就是开闭原则,依赖倒转,里氏代换,单一职责等一定要使用到位,不然像货物分类和会员分类这样的问题在第一次作业上面都有相似甚至一样逻辑的代码,但是只顾一时写的快,到了第二次作业还要重新写一遍,纯纯浪费时间。
五、总结
总的来说这两次大作业主要的考察方向就是面向对象七大设计原则的实践,和对类设计的考虑,反而在算法方面都是加加减减的普通设计,总的来说比上几次还是简单的。但还是存在很多要改进的地方。
首先七大设计原则完全符合是不可能的,编程的经验还是偏少,有好多地方结构都是比较混乱的,迭代起来修改起来也是比较麻烦。
然后刚开始类之间的方法调用也是比较混乱的,有很多地方都是为了图方便直接写成了public,到后面修改起来也是很麻瓜。
最后也是注释写的很少,基本上没有(就是没有),每一次都提醒自己要写注释,但每一次都懒得写,直到要改的时候看着几百行的代码又想着当时怎么不写。
面向对象课程就要结束了,blog也写不了几次了,剩下的javafx也要好好学,要多进行练习。
不管是接口,多态,类设计还是容器,只有写得多了才能熟练使用,一定要加强自己的基础编程能力。


浙公网安备 33010602011771号