NCHU第三次oop作业-blog
前言:
进入了这个学期学习Java的第三个阶段,我们对于Java的体系结构有了进一步的了解。这一阶段的题目集总体来说不难,但对于程序的编写规范来说有许多规定需要遵守,例如程序中的类需要遵守单一原则以及开-闭原则等,特别是对于要写比较多的类的时候保证程序内的单一原则是非常重要的。本次的题目集7(7-1)、(7-2)是对于图形卡片游戏的排列和分组的递进设计,以及题目集8、题目集9,也是对于ATM机类结构的递进设计。可以说在这次的作业中我们对于前面学习到的类的封装性及类间关系设计有一次更深层次的理解。与此同时也是对于代码的结构的设计提出了新的要求,因此我们在这次的作业中也体会到了代码的复用性不是粘贴复制而是要将代码结构层次给设计好以便于后续的改写和调用,以达到减少代码书写量的目的。
设计与分析:
①题目集7(7-1)、(7-2)两道题目的递进式设计分析总结:
1) 题目集7(7-1)、(7-2)这两道题目是分别对于图形卡片排序游戏、图形卡片分组游戏有不同的要求,但是它们类的结构是基本相同的。
如下给出两程序的类图
题目集7(7-1):

题目集7(7-2):

2)从类图上可以看出两程序的类结构基本相同,因此可以研究两程序的递进设计。在题目集7(7-1)中是并不需要将卡片进行分类的,因此只需要一条链表就可以了,而在题目集7(7-2)中是要求卡片分组的,因此在DealCardList类中与题目集7(7-1)中不同。我这里是将不同的卡片用了不同的ArrayList链表来区别,所以可以将同一类型的图片归到同一个链表中。
这里给出两程序在选择排列分组的程序片段:


3) 同样,对于链表内卡片的面积大小是需要进行排列的。这两个程序也是用到了递进的设计,同样的用到了Comparable接口,来进行对于卡片面积的排序。(节选题目集7(7-1)Card类)

4) 在实现题目集7(7-2)中的卡片分类中,可以看到用到了多条链表。回过头来看,其实在做后续的程序维护来看是不友好的,不符合程序的设计理念的。因此在这里可以设计成一条链表,然后将卡片类型的名称作为分类依据然后在进行分类,这样做与分成多条链表的设计来讲会更好些,同时也降低了程序在编写的时候多条信息的繁琐。
5) 在这两个程序的编写过程中也主要用到了类的继承、多态性使用方法以及接口等的应用,在逐渐的学习过程中掌握类的继承,和多态性,以及接口对于我们在编写程序上有很大的帮助和便捷性。
例如在写不同的图形类中,我这里是继承了一个Shape抽象类:

6) 在这个抽象父类中主要是有图形的名称属性和求面积的方法以及后续的toString()的方法,在后续写的子类中只需要重写其中的求面积的方法即可,极大的减少了书写代码的工作量也优化了相应的代码中类的结构,符合面向对象的编程原则的。因此我们是更加需要将这种编码的思想融入到我们后续的面向对象的学习之中的。
7)分析题目集7(7-1)和题目集7(7-2)两程序 的圈复杂度:
题目集7(7-1):
Parameter Value
========= =====
Project Name
Checkpoint Name Baseline
Created On 15 Jun 2021, 15:22:34
Files 1
Lines 327
Statements 149
Percent Branch Statements 14.8
Method Call Statements 98
Percent Lines with Comments 2.1
Classes and Interfaces 3
Methods per Class 5.67
Average Statements per Method 7.35
Line Number of Most Complex Method {undefined}
Name of Most Complex Method DealCardList.DealCardList()
Maximum Complexity 8
Line Number of Deepest Block {undefined}
Maximum Block Depth 8
Average Block Depth 3.85
Average Complexity 2.73
--------------------------------------------------------------------------------------------
Most Complex Methods in 3 Class(es): Complexity, Statements, Max Depth, Calls
Card.setShape() 1, 1, 2, 0
DealCardList.DealCardList() 8, 23, 5, 17
Main.main() 5, 14, 4, 11
题目集7(7-2):
Parameter Value
========= =====
Project Directory D:\应用\Java\eclipse\eclipse-workspace\text21\src\text21\
Project Name
Checkpoint Name Baseline
Created On 15 Jun 2021, 15:27:11
Files 1
Lines 425
Statements 217
Percent Branch Statements 20.3
Method Call Statements 193
Percent Lines with Comments 2.4
Classes and Interfaces 3
Methods per Class 5.67
Average Statements per Method 11.12
Line Number of Most Complex Method {undefined}
Name of Most Complex Method DealCardList.cardSort()
Maximum Complexity 13
Line Number of Deepest Block {undefined}
Maximum Block Depth 8
Average Block Depth 3.45
Average Complexity 4.73
--------------------------------------------------------------------------------------------
Most Complex Methods in 3 Class(es): Complexity, Statements, Max Depth, Calls
Card.setShape() 1, 1, 2, 0
DealCardList.cardSort() 13, 16, 4, 36
Main.main() 6, 17, 4, 14
可以看出这两个程序相对于我上一阶段写的程序的复杂度整体来说降低了不少,但是还有问题的存在。用粗体标出的就是最大的圈复杂度以及平均的圈复杂度,在题目集7(7-2)中表示出它的最大圈复杂度达到了13,明显高于老师说的10。因此经过分析,我认为还是在对于卡片的排序过程中因为我先前将不同的卡片分成了许多组导致的后续圈复杂度增高。后续还有很大的改进和学习空间
②题目集8ATM机仿真题目的设计思路分析总结
1)对于ATM机仿真程序的设计,根据题目要求的各个机构之间的关系可以建立类图,我首先的思路是寻找出其中的关系。其中有中国银联、银行、银行用户、银行账户、银行卡、ATM等几个关系需要捋清。其后是需要考虑其中的信息是如何存放的。首先是对于银联是应该包含银行信息的,然后银行中包含银行账户的,其次是银行账户包含用户信息和卡信息的。但在后来考虑调用信息不是很方便,之后看过了老师给出的程序明白了其中可以双向调用,极大的方便了查找,也方便了后续的程序类的添加和修改。说回我自己写的程序其中的一大坑点是对于用卡号去寻找相对应的主账户的时候发现会很麻烦。
先给出题目集08的类图:

2) 可以看出各个类之间是紧密联系的,各个的信息调用也比较符合正常的逻辑习惯。但是就是会在查寻信息的时候会很麻烦,这是后续需要改进的一个地方。其次是在于导入用户信息的时候,我认为我将其做复杂了,这里是创建一个Information类来当作联系各个类之间的中介类,其中是将银行、用户、银联、账户、卡都分别做一个方法将其写入信息。但是这可能会将程序变得繁重。
3) 在主类中进行操作,也就是依据卡号来找到对应的账户、银行。我是如下这样写的:

可以看出通过四个for循环才将卡号匹配,我认为是极其复杂的,但是苦于当时没有更好的解决办法,只能用这个方案。
4)在编写这次的ATM机的程序中还利用到了ArrayList链表的迭代器,通过学习与使用发现是方便我们对于链表内的对象进行查找的,但是后来发现利用链表的这个迭代器是不能够寻找到元素的位置信息的,也就是说无法通过迭代器来提取出我想要的那个对象,因此最后还是选择使用了我最熟悉的for循环。
5)这个程序中还用到了 类间关系设计(关联、组合及依赖),因为要表示类与类之间的关系。在类之中是用聚合来表示其间的关系的,例如(如图):


6)分析题目集08的圈复杂度:
Parameter Value
========= =====
Project Directory D:\应用\Java\eclipse\eclipse-workspace\bankSystem\src\bankSystem\
Project Name
Checkpoint Name Baseline
Created On 16 Jun 2021, 19:15:45
Files 8
Lines 594
Statements 374
Percent Branch Statements 5.6
Method Call Statements 203
Percent Lines with Comments 2.7
Classes and Interfaces 8
Methods per Class 8.63
Average Statements per Method 3.91
Line Number of Most Complex Method {undefined}
Name of Most Complex Method Information.chackBank()
Maximum Complexity 8
Line Number of Deepest Block {undefined}
Maximum Block Depth 8
Average Block Depth 1.88
Average Complexity 1.32
--------------------------------------------------------------------------------------------
Most Complex Methods in 7 Class(es): Complexity, Statements, Max Depth, Calls
Account.addCard() 1, 1, 2, 1
ATM.setNumber() 1, 1, 2, 0
Bank.setListATM() 1, 1, 2, 0
Card.setPassword() 1, 1, 2, 0
ChinaUnionPay.setListBank() 1, 1, 2, 0
Information.chackBank() 8, 7, 3, 10
User.addAccount() 1, 1, 2, 1
可以看出这个程序的圈复杂度控制的比较好,主要是信息类中的复杂度高一些,也是因为其中的录入的信息比较复杂。
③题目集9ATM机仿真题目的设计思路分析总结
1)给出题目集9类图:

2)相对于题目集8中的ATM机题目来说题目集9中的程序可以说是08的一个迭代的程序,其中的要求是加多了贷款账户、跨行取款、以及贷款利率和跨行手续费等需求。是可以通过08中的程序进行重构来达到迭代升级的需要的。但是通过参考了老师的程序后,借用了老师的基本类结构,然后再写出来的。
3)通过观察上面的类图可以发现,类之间的关系是通过双向绑定的,通过双向的关系可以迅速寻找出相对应的卡信息。相对于我上一个程序来说是非常有利于做信息的查寻功能的,有了双向绑定通过卡号来寻找账号的功能实现是具体的实现是如下的:

也是用迭代器来查寻到不同的账户的。
4)由于需要完成设计两个账户,一个是借记账户另一个是贷记账户,因此需要设计一个抽象的账户类来作为这两个类的父类。抽象账户类中包含账户的主要信息,其属性为账户编号、账户余额、账户类型。通过设计抽象的账户类可以有一个更好的类之间的结构。也会比较好录入信息,只需要将不同的账户类型录入到不同的实体账户类之中就可以了。(如下是两个实体账户类):


5)其次是编写这个程序内的其他的一些类,有Withdraw类、ValidateData类。Withdraw类主要的功能是对于取款的一些操作,其中有设置跨行取款的费率、判断是否为跨行取款以及贷款的一些简单的计算,以下是部分实例:

6)分析题目集09的圈复杂度:
Parameter Value
========= =====
Project Directory D:\应用\Java\eclipse\eclipse-workspace\bankSystem01\src\bankSystem01\
Project Name
Checkpoint Name Baseline
Created On 16 Jun 2021, 19:43:03
Files 12
Lines 902
Statements 505
Percent Branch Statements 9.3
Method Call Statements 200
Percent Lines with Comments 9.8
Classes and Interfaces 12
Methods per Class 8.00
Average Statements per Method 3.69
Line Number of Most Complex Method {undefined}
Name of Most Complex Method Withdraw.Withdraw()
Maximum Complexity 27
Line Number of Deepest Block {undefined}
Maximum Block Depth 7
Average Block Depth 1.98
Average Complexity 1.68
--------------------------------------------------------------------------------------------
Most Complex Methods in 13 Class(es): Complexity, Statements, Max Depth, Calls
Account.getAmountbyCardNO() 3, 7, 4, 6
ATM.setBank() 1, 1, 2, 0
Bank.setATMList() 1, 1, 2, 0
Card.checkPassword() 1, 1, 2, 1
CreditAccount.setOverWithdrawFee() 1, 1, 2, 0
DebitAccount.DebitAccount() 1, 1, 2, 1
GetBalance.getBalance() 1, 1, 2, 1
Main.main() 5, 111, 4, 60
UnionPay.removeBank() 1, 1, 2, 1
User.removeAccount() 1, 1, 2, 1
ValidateData.validateData() 9, 23, 4, 22
Withdraw().withdraw() 17, 27, 7, 31
Withdraw.Withdraw() 27, 44, 7, 46
分析这个程序的最大圈复杂度,是在于Withdraw类之中,通过我的分析还是在一判断是否跨行以及贷款,使用了较多的if-else语句增大了判断的工作量,使用会导致程序运行时的圈复杂度远远超过了规定的标准。所以说对于这样的程序的话我认为在于判断跨行取款以及贷款应该需要再进行简化。
采坑心得:
总的来说这次的题目其实题量不大,有的是需要我们前期对于程序类结构的规划,然后才能写好程序,在这其中也有遇到过许多困难。
1)在对于题目集7 - 2中的ArrayList链表进行泛化 的时候本应该是对于Card类进行泛化,然后对于ArrayList中我起先是对于Integer进行泛化,如下:

这样的操作其实是不符合题目的要求的。后来还是改为了:
ArrayList<Card> cardList = new ArrayList<Card>();
2)其次是对于多态性之间的使用还不是很熟悉,例如重写一个compareTo接口其内的大小不知道如何比较:

3)然后就是对于ATM机类之间的设计于隶属关系总是无法构建一个完整的类关系图,导致编写程序的时候无从下手。只能通过银行系统各个机构的相对应的关系来规划相对应的类的结构关系。其次是对于类中的链表中的泛型需要有更深的理解。还有对于重写方法需要更高的学习例如完成Comparable、和Comparator接口:

改进建议:
1)先是对于我的代里的一些方法的最大圈复杂度很高感到不满意,后期写程序的时候可以考虑自己程序的复杂度然后在进行编写程序。以达到降低圈复杂度的目的,从而来简化自己的程序。
2) 学习到了这个步骤,就应该对于我们写的程序进行更加深入的学习,例如需要对于程序类的结构设计需要有更加好的设计与思路,写程序之前不应该草草的自己开写,是应该对于编写前认真的阅读需求,然后再提出自己的对于程序的思路,对于整个的程序框架需要有一个设计过程或者思考过程。
3)虽然这次的题目集要求的主要是对于我们继承、多态性使用方法以及接口的应用、类的封装性及类间关系设计等要求,但是我认为这次的题目集要求的是我们在于程序重构自己有自己的想法,以及对于程序的设计上有自己的初步的看法。因此还是需要提高自己的的程序设计上的能力。
总结
我认为我们这个专业的学习模式本就是需要自己本身慢慢培养出强大的自学能力,才能够在短时间内提升自己的程序编写能力。其次是对于本阶段的题目,虽然本次题目的题量很小但是对于我们对于程序的规范性下提出要求例如类间关系设计,同时也是提高我们学习java的能力。
在通过这个阶段的学习之后我认为我们这只是学习系统的Java的基础,如果需要提高之间仍需不断地努力去了解更多的其他的知识,还有去学习其他人编写的优秀程序。与此同时是要更多的去培养自己的自学能力,以及自己在Java学习过程中要去不断的扩充自己的知识面,从而来提高自己的能力。
NCHU—软件学院
HYC

浙公网安备 33010602011771号