面向对象程序设计第三次博客
1、前言
- 题目集七应用了ArrayList泛型以及继承和多态,Comparable接口及泛型的应用,同时也用到了单一职责原则和开闭原则,有两道题,题目难度适中。
- 题目集八和题目集九都是对ATM机类的结构设计,递进式的两道题,难度都挺难的,题目集八和题目集九都是一道题。
- 在题目集八之后老师给了我们题目集八的源代码,并且让我们增加借记卡的类,设计类之间的关系是一个难点。
2、设计与分析
题目集7(7-1)、(7-2)两道题目的递进式设计分析总结
- 虽然说两道题都是排序游戏,但是还是很麻烦,因为第二个题目的排序与第一个不一样,就需要重写排序的那一块代码,7-1的PowerDesigner类图和SourceMonitor生成报表内容如下:
- PowerDesigner类图
![]()
- 从类图中可以看出所有的图形类都有一个父类,然后在卡片类里面进行排序的算法
- SourceMonitor生成报表内容
![]()
- 由图可知圈复杂度为8,没有使用很多的判断语句,只是在判断形状是否成立的时候使用了if语句来判断是否成立。
- 7-2的PowerDesigner类图和SourceMonitor生成报表内容如下:
![]()

- 由图可知类之间的关系并没有改动太大,圈复杂度也没有变化,是因为圈复杂度只是用在判断数据上面,只是输出的方式改变了,还有排序的方式变了,第一题是从小到大依次排序,第二题则是在每一个图形集合里面进行排序:
- 第一题的排序算法:
public void cardSort() {
for(int i = 0;i < cardList.size();i ++) {
for(int j = 0;j < cardList.size() - i - 1;j ++) {
if(cardList.get(j).getShape().getArea() < cardList.get(j+1).getShape().getArea()) {
Collections.swap(cardList, j, j + 1);
}
}
}
}
public double getAllArea() {
double total = 0;
for (int i = 0; i < cardList.size(); i++) {
total += cardList.get(i).getShape().getArea();
}
return total;
}
- 第二题的排序算法:
public void cardSort() {
for(int i = 0;i < cir.size();i ++) {
for(int j = 0;j < cir.size() - i - 1;j ++) {
if(cir.get(j).getShape().getArea() < cir.get(j+1).getShape().getArea()) {
Collections.swap(cir, j, j + 1);
}
}
}
for(int i = 0;i < rec.size();i ++) {
for(int j = 0;j < rec.size() - i - 1;j ++) {
if(rec.get(j).getShape().getArea() < rec.get(j+1).getShape().getArea()) {
Collections.swap(rec, j, j + 1);
}
}
}
for(int i = 0;i < tri.size();i ++) {
for(int j = 0;j < tri.size() - i - 1;j ++) {
if(tri.get(j).getShape().getArea() < tri.get(j+1).getShape().getArea()) {
Collections.swap(tri, j, j + 1);
}
}
}
for(int i = 0;i < tra.size();i ++) {
for(int j = 0;j < tra.size() - i - 1;j ++) {
if(tra.get(j).getShape().getArea() < tra.get(j+1).getShape().getArea()) {
Collections.swap(tra, j, j + 1);
}
}
}
}
public double getAllMax() {
double max = 0;
double[] area = new double[4];
for(int i = 0;i < cir.size();i ++) {
area[0] += cir.get(i).getShape().getArea();
}
for(int i = 0;i < rec.size();i ++) {
area[1] += rec.get(i).getShape().getArea();
}
for(int i = 0;i < tri.size();i ++) {
area[2] += tri.get(i).getShape().getArea();
}
for(int i = 0;i < tra.size();i ++) {
area[3] += tra.get(i).getShape().getArea();
}
for(int i = 0;i < 4;i ++) {
if(max < area[i]) {
max = area[i];
}
}
return max;
}
- 第一题的输出:
public void showResult() {
System.out.println("The original list:");
for(int i = 0;i < cardList.size();i ++) {
System.out.print(cardList.get(i).getShape());
}
System.out.print('\n');
System.out.println("The sorted list:");
cardSort();
for(int i = 0;i < cardList.size();i ++) {
System.out.print(cardList.get(i).getShape());
}
System.out.print('\n');
System.out.printf("Sum of area:" + String.format("%.2f",getAllArea()));
}
- 第二题输出:
public void showResult() {
System.out.println("The original list:");
System.out.print("[");
for(int i = 0;i < cardList.size();i ++) {
System.out.print(cardList.get(i).getShape());
}
System.out.println("]");
System.out.println("The Separated List:");
System.out.print("[");
for(int i = 0;i < cir.size();i ++) {
System.out.print(cir.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < rec.size();i ++) {
System.out.print(rec.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tri.size();i ++) {
System.out.print(tri.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tra.size();i ++) {
System.out.print(tra.get(i).getShape());
}
System.out.print("]");
System.out.print('\n');
cardSort();
System.out.println("The Separated sorted List:");
System.out.print("[");
for(int i = 0;i < cir.size();i ++) {
System.out.print(cir.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < rec.size();i ++) {
System.out.print(rec.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tri.size();i ++) {
System.out.print(tri.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tra.size();i ++) {
System.out.print(tra.get(i).getShape());
}
System.out.print("]");
System.out.print('\n');
System.out.printf("The max area:" + String.format("%.2f",getAllMax()));
}
- 其他的大致一样,只是这两处有很大的不同。
题目集8和题目集9两道ATM机仿真题目的设计思路分析总结
- ATM机仿真题目考查的是对类的设计,需要自己设计类,并且需要遵循几大法则,,难度主要是对类的掌握,需要设计多少个类,还需要遵循单一职责原则和开闭原则。
- 题目集八:
- PowerDesigner类图和SourceMonitor生成报表内容如下:
![]()

- 由图可知圈复杂度为23,判断语句用的比较多,主要是在判断数据是否正确的方法中使用,如下图显示,圈复杂度高的原因都在这,应用了很多嵌套来判断数据,在后面其实可以用switch直接判断的:

-
由类图可以清晰的得知设计的类之间的关系,主要就是wrong类之中的进行的操作,包括数据初始化等等方法都在wrong类里面,这里的设计不合理,不符合单一职责原则,也是用一个list接口把数据输入之后在进行各种比较和判断,首先要进行的是数据的的初始化,因为老师给的数据都是单独的,所以我在card类里面再加了三个私有属性:
![]()
-
分别是姓名,银行名和账户,所以初始化数据时就成为了下图:
![]()
-
这些数据声明都处在Initial方法中,而后在Operate方法中的第一行代码就是调用Initial方法进行数据的初始化,同时也在wrong类里面设置了五个判断数据是否正确的方法:
![]()
![]()
-
继续下去就是判断数据是否正确的方法,就是上图中if嵌套语句很多的代码。在判断完成数据的正误后,就执行了对资金的取款和存款操作,先分清楚账户再进行存取款的操作,然后进行最后的输出:
![]()
-
题目集九:
-
题目集九在做之前老师就已经给了我们他写的题目集八的代码,看了一下老师写的代码和我写的,才发现我写的代码质量太差,老师很明确的考虑到了账户和卡号之间的关系,然而题目集九要求我们做的是再加入一个银行,atm机之间实现跨行取款,但是要收利息,然后还增加了一个借记卡的使用操作,在借记卡有余额时不进行利息扣费,但是当借记卡透支时需要执行利息的操作,我们要做的只是加入这些。
-
PowerDesigner类图和SourceMonitor生成报表内容如下:
![]()
-
由图可知,再对比一下上面的我写代码的类图,老师的类图设计复杂了很多,特别是一种嵌套设计,达到了互相调用的目的,而我在老师的类图上做了一些补充的修改,我把Card类设置成了父类,它有两个子类:Debit类和Credit类,代表着普通卡和借记卡,原本的普通卡只是一个card类,但是现在它和借记卡同属于card类,这样设计更好判断是普通卡和借记卡,同时我在Debit类和Credit类中分别设置了卡的名称的属性,在后面的实现卡的借记中起到了重要作用。

-
这是SourceMonitor生成报表内容,由图可知圈复杂度反而降了,那是因为在老师设计的类中,判断数据是否正确的方法简化了,老师把几个判断数据的方法都设置了单独的方法,然后我自己又加了Validate类来判断数据是否正确,这才把圈复杂度降下来一点,在代码中,检测数据和最后的金额存取我同样的用了很多的if语句才导致圈复杂度高。
-
老师直接在main方法中初始化了所有的数据,我需要做的只是再添加一些新增的数据,老师的嵌套设计的方法如下图:

-
这样做的好处是通过调用把所有的实体类都连接起来,在后面引用数据的时候变得更加快捷,初始化完成之后就开始了对数据进行操作,还是一样,先验证数据是否正确:
![]()
![]()
-
判断数据正误,如果是错误,则打印相应的数据并且结束程序:
![]()
![]()
-
测试完数据正误之后便是调用数据进行修改,也正是存取款的操作,直接用代码为大家呈现:
public void withdraw() {
Account account = Account.getAmountbyCardNO(cardNO);
double balance = account.getBalance();
ATM aTM = ValidateDate.getATMbyATMID(getUnionPay(), getATMID());
//跨行取款
double amount1 = 0;
if (account.getBank().getBankNO() != aTM.getBank().getBankNO()) {
if(aTM.getBank().getBankNO().equals("1001")) {
amount1 = 0.02 * amount;
}
if(aTM.getBank().getBankNO().equals("1002")) {
amount1 = 0.03 * amount;
}
if(aTM.getBank().getBankNO().equals("1003")) {
amount1 = 0.04 * amount;
}
}
double amount2 = amount;
if(account.getBalance() < 0) {
amount2 = 1.05 * amount2;
}
else {
if(account.getBalance() - amount < 0) {
amount2 = -(account.getBalance() - amount);
amount2 = 1.05 * amount2;
amount2 += account.getBalance();
}
}
account.setBalance(balance - amount2 - amount1);//取款更新余额操作
if((-account.getBalance()) > 50000) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}
if(amount >= 0) {
showResult(account,1);
}else {
showResult(account,0);
}
}
public void showResult(Account account,int flag) {
String type = "";
if(flag == 1) {
type = "取款";
}else {
type = "存款";
amount *= -1;
}
ATM aTM = ValidateDate.getATMbyATMID(getUnionPay(), getATMID());
String userName = account.getUser().getName();
String bankName = aTM.getBank().getBankName();
System.out.println("业务:" + type + " " + userName + "在" +
bankName + "的" + ATMID + "号ATM机上" + type + String.format("¥%.2f", amount));
System.out.println("当前余额为" + String.format("¥%.2f", account.getBalance()));
}
- 两道题只是增加了一个借记卡,还有一个跨行取款的区别,但是我认为代码变了很多,不只是类之间的关系,增加的方法也是一个原因,增加的方法太多导致在写的时候容易出错,但是只要类之间的关系清晰了,接下来就是设计方法到底是在哪个类里面被调用,明白关系之后就能写出相应的程序。
3、踩坑心得
题目集七(7-2)
-
这道题的排序一开始是没有想清楚到底怎么排,我先是用了第一题的排序然后用每一个图形单独去调用排序的方法,后面发现没有过题,排序还是错的,然后仔细看题目发现了不只是中括号里面需要排序,图形的平均面积还要进行从小到大的排序,所以就先比较数值大小,然后再在各个中括号之间比较大小并且进行一个排序:
![]()
-
这是寻找最大值的查找方法:
![]()
-
这两个方法调用,才能让数据进行最后的排序,而且一些符号需要很认真的去注意,不小心就会输出错误:
public void showResult() {
System.out.println("The original list:");
System.out.print("[");
for(int i = 0;i < cardList.size();i ++) {
System.out.print(cardList.get(i).getShape());
}
System.out.println("]");
System.out.println("The Separated List:");
System.out.print("[");
for(int i = 0;i < cir.size();i ++) {
System.out.print(cir.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < rec.size();i ++) {
System.out.print(rec.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tri.size();i ++) {
System.out.print(tri.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tra.size();i ++) {
System.out.print(tra.get(i).getShape());
}
System.out.print("]");
System.out.print('\n');
cardSort();
System.out.println("The Separated sorted List:");
System.out.print("[");
for(int i = 0;i < cir.size();i ++) {
System.out.print(cir.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < rec.size();i ++) {
System.out.print(rec.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tri.size();i ++) {
System.out.print(tri.get(i).getShape());
}
System.out.print("]");
System.out.print("[");
for(int i = 0;i < tra.size();i ++) {
System.out.print(tra.get(i).getShape());
}
System.out.print("]");
System.out.print('\n');
System.out.printf("The max area:" + String.format("%.2f",getAllMax()));
}
题目集八
-
题目集八主要还是卡在了数据输入上面,数据的输入有两种方式,一个是一长串的数据,还有一个是查询所剩余额的数据操作,当时想着可以用字符串去比较,可是后来想到了接口这钟方法,接口的方法中有一个可以得知接口的长度,所以我设置了大于一执行一个方法,等于一执行另一个方法:
![]()
![]()
-
当数据只有一个时执行查询方法,数据多个时就判断数据的正误然后跳转到下方的具体对余额的处理方法。
题目集九
-
在题目集九中的主要难点就是对借记卡的一个操作,借记卡是和普通的卡不一样的,但是又属于账户下的卡,所以我就把卡作为一个父类,然后普通卡和借记卡都为子类,同时在两个子类中都定义了自身的卡的属性,可以很方便的查找到到底是属于哪一类的卡:
![]()
-
具体的查找是哪一类卡的方法如下,这样可以省去大量的if语句来判断是哪一种;类型的卡:
![]()
-
然后在更新余额的时候也卡了,借记卡中的利息和跨行取款的利息不能去重合,也就是说只能算借记卡中透支的利息,当借记卡透支时,就不需要在计算跨行取款的利息,最后写出来的时候数据对不上,调试了很久才对上:
![]()
-
然后在最后结果的输出方式也改变了,需要加一个“业务:”之前并没有注意导致最后的输出错误,加上之后就通过了。
4、改进建议
- 圈复杂度的问题还是要注意,总是太大的圈复杂度会让代码的可读性极差,就像题目集八的判断数据的方法,老师写的和我写的圈复杂度相差20,有很多种方法可以降低圈复杂度,以后要多多注意。
- 对类之间的设计还是要想更多的方法,在看了老师的类图之后知道我差的太远了,类之间的关系要想清楚再开始写,做到单一职责原则和开闭原则,哪个类作为父类在题目集九之中也是想了很久很久,最后才新设置类,在写类图的关系的时候我觉得应该扩宽思维。
- 还要进行适当的代码优化和写上相应的注释,我还没有养成在写代码中写注释的习惯,代码的格式也应该注意到。
- 这次的三次题目集都是满分,可是做的时间有点慢,原因是在题目集开放前几天并没有去做,之后需要多多改进。
5、总结
- 这是本学期最后一次的博客作业总结了,一个学期以来题目的质量也是越来越高,题目的难度也是在不断的增加,但是难度增加可以更加的锻炼自己编程能力和对类的设计能力,这些题目我还没有完全理解透,在以后会多多打开作业查看。
- 题目难易度我觉得偏难,好在通过自己的学习跟上来了,让我更加感觉到自己的不足,培养自己的自学能力,和坚持能力。
- 对类的设计之中需要更加深入的研究,思维需要开阔,要多思考类之间的关系,做到两个原则。
- 对类之间的设计还需要老师多多深入讲解,讲解为什么这样设计类之间的关系,希望老师多讲一些注意事项。






















浙公网安备 33010602011771号