第三次博客作业
Posted 板
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三次博客作业相关的知识,希望对你有一定的参考价值。
第三次博客作业
目录
一,对作业的前言
二,设计和分析
三,踩坑心得
四,改进建议
五,总结
一,对作业的前言:
总体来说我,我认为这几次的作业其实不难,仅仅是为了得到卷面的100分来说是不难的,但是这几道一考验的都是实实在在的对java面向对象的思考与实践,要从C语言里的,面向过程的变成的思想转变为面向对象的思想。说起来容易做起来难。抽象类的意义?接口的意义?语法规则?以及什么时候抽象类?抽象类有什么好处?各种各样的数据之间的关系是怎样的?要读取要怎么读取?多态好处体现在哪里?如何做到多态?如何使代码尽可能的简洁?这些思考才是这几次作业的关键所在。
二,设计与分析:
1,题目集7,(7-1)
卡片排序题,大概要求为提供不同形状的卡片,和其要求出面积对应需要的数据。需要计算出各个卡片的面积,对相同类型卡片面积求和,之后对不同类型卡片面积和进行排序。
思路:一个非常典型的有关于实物类的应用,多态应用。首先,图形肯定是实物类,不同的图形相互有不同的计算方法。因为都是图形的缘故,自然是要设计抽象父类shape类,这样会易于多态方便后面将要出现的链表。因为这道题,显然出现了多个图形,这时候要使用泛型链表来进行储存,不能再用垃圾的数组了。卡片是实物类,它才是这段代码的主角,形状,面积都是卡片的属性,要进行排序的也是卡片,那么链表显然就是卡片的链表了。因为每个卡片都是要参与排序的,所以要设计一个接口,使得卡片可以被排序,所以有接口compareable。类图如下:
按照这个思路,再根据类图,我们很快着手写代码。
最先写的是抽象父类shape,只有声明,没有方法实体。过于简单就不赘述了。
而后是shape的各个子类, 因为形状都是继承与父类,而且功能是一样的,我写出正方形来代替其他的图形,正好也可以对shape讲解。
构造器(183-186),求图形面积(188-190),重写父类object方法tostring以便后来进行输出(193-196),判断是否合法(198-203)。
写好各个形状之后,显然就要写card了,因为卡片是要可以被排序的,所以它是调用接口comepareable(),接口只有签名不写了。
卡片,属性是形状,可以被排序,重写tostring方便输出。
卡片写完了,就是差一个业务类,将所有卡片集合,进行排序输出。
接下来的就是业务类DealCardList
我挑核心代码讲,构造器(242-270)都是大量重复的代码。排序的方法(287-300),一个冒泡排序法使得ArrayList里面的card都是有序的。接下来,按序输出就可以了。
结合sourceMonitor分析代码:
最大圈复杂度:5
最大圈复杂度方法:排序卡组cardsort()。
基本符合要求。
2.题目集7,(7-2)
题目中,给的还是卡片,规则只有一个不同,就是要按照,所有圆形面积相互排序输出,所有矩形面积相互排序输出,所有园相互排序输出。说白了就是相同的形状之间排序而不是所有的图形一起加入排序。
思路:
这道题简直简单,我所有的都可以排序的话,想要剥离出某一部分出来进行排序何止是简单,简直有手就行。所以这里是第一种完成方法:既然是有已经排好的,那么我只要吧排好的链表遍历,遇到圆形就输出,那么我就输出了所有的圆形的排序,同理,矩形,三角形可以通过遍历筛选得到答案。我这里有第二种方法,就是我的业务类还有圆形,矩形的链表。
然后我写一个链表排序法出来,照样可以得到答案。
两道题目对比总结:
多亏了第一道题的简洁明了,第二道题明显很简单就完成了。这次的作业我只能说对抽象类,接口的使用多了一些心得。
题目集8
这次的题目写的是一个ATM机,要求可以实现用户通过卡号和密码,在对应的ATM机上实现,存款,取款。以及查询。并且不能跨行操作,出现的各种问题要进行处理并进行提醒,提高软件的稳定性,不能崩溃。
由于这个题目体量比较大,我将结合类图进行分析:
最最最核心的流程是将数据储存到缓存中,然后结合用户所给的信息进行查询,判断合法性。最最最要思考的是,银联,数据之间的关系。得到老师的提示之后我做出如下判断,银联包括所有的用户,所有的银行,银行包括所有的ATM机,用户的属性有账户,账户的属性有余额,银行卡,银行卡的属性有卡号和密码。我简单的用流程图描述一下如下:
好的,那么自然是从上往下进行代码编写,首先是银联类:
银联就是银行的集合。
然后就是银行:
银行是账户和ATM机的集合。
用户:
账户是用户的,所以用户有账户的链表。
账户:
银行卡:
ATM机:
注意:以上都是实物类,每个类你内容就只有geter和seter所以不再赘述。
Database数据库:
因为这道题有大量的数据,同时要进行大量的遍历查询,以及修改,我将数据全部统一存入数据库database这样可以避免自己写昏了头。
接下来我要讲的是这道题的业务类,数据交互的中心,Business():
整个题目的灵魂所在,这道题,无非就是遍历查找,然后对查找到的东西进行修改,那么这个类就是这道题查找和修改的集中地,我想细细讲解。
既然是数据交互中心,自然属性是database,只有这样才好遍历,既然是处理,那么还有用户输入的东西也是它的属性。如下图:
得到了卡号和密码,我希望得到账户,以读取信息或者进行修改,那么这是对应的方法searchAccountBycard():
这确实是本题的难点之一了,在写的过程中我也曾怀疑,真的是这样的吗?如此多的循环显然是不好的。我记得老师说过要用双向链表,但是我用不来,那就老老实实的单向遍历循环吧。(双向链表在第九次题目集中论述)。所以我就写了这么个东西出来,遍历用户,遍历账户,遍历卡,再对比,简直愚蠢,但是我毫无办法。
既然我得到了用户要在哪个ATM机上操作,我自然就得通过ATM机的号码得到该ATM机,方便得到ATM机的各项属性searchATM():
遍历银联,遍历银行,遍历atm机,判断找出。
得到了账户,其他的操作就显得易如反掌,比如说查询showBalance():
比如说取款withDrawal():
或者说判断是否在对应的银行的ATM机上进行的操作ifRightBank():
这里我是已经写昏了头从147-158的循环根本就是重复劳动,因为我已经有可以从卡号得到卡的方法了,但是我依旧写了循环。
判断卡是否存在ifCardExist():
这里也是,唉,本来可以减少很多重复劳动的,啧。
显示结果showResult():
至此,所有需要的模块已经完成,只需要一个流程串起所以的方法就可以了,接下来就是我程序的丑陋的第二个地方。长长的主函数Main()。
第一段, 是做循环从用户得到输入:
第二段,是根据输入判断用户是否是查询:
第三段,是判断各种合法性:
我认为,第三段是不应该存在的,它们应该被写成business的一个方法,这个方法专门负责输出。
类图:
结合sourMonitor分析:
最复杂的方法:main()
最大圈复杂度:8
最大圈复杂的在204行,方法是showResult(),因为它是遍历用户,账户,卡再加了一个判断。
平均圈复杂度:2.13
平均复杂度:1.61
小结:自己写的代码,确实,漏洞百出,到处都存在不合理,各种混乱,各种写重复代码,写出的类各种不满足面向对象的要求。
4.题目集9
题目集9的ATM仿真训练与题目集8的相比,变得可以跨行进行取款了,但是取款要收手续费,而且不同银行的手续费是不一样的,同时推出信用卡,信用卡是可以进行透支的,但是透支会产生手续费,其余的不变。
这道题,我们在编写的时候事根据老师写的题目集8进行功能拓展所以在数据存储上会有很大的不同,但这恰恰是我所需要的。
此题,重点是双向链表的使用,我需要从卡号得到账户,而不是从银联开始遍历,将所有的用户,账户,卡号进行遍历就像我之前做的那样,这种双向链表大大减少了程序的运行时间。
思路:在银联中通过卡号,可以得到对应的账户,在银联中通过ATM机号,可以得到对应的归属银行,利用得到账户和归属银行进行存取款的操作。
代码自底层到高层:
实物类card():
我们应该注意的是,card本应该只有卡号和密码的属性,但是现在加上了账户属性为什么card的属性为什么不是账户呢?,但其实你那里可以直接得到卡呢?卡那么多张,真要找到卡,还得看account,所以属性是银行就可以理解了。
实物类ATM():
ATM的属性本应只有对应的号码,但是现在有银行的属性。
再范围大一点的实物类账户类Account():
账户的属性是,账户号,透支额度,所属银行,所属用户。
实物类用户:
用户的属性是名字,id,和账户的链表。
实物类银行:
属性是银行id,银行名,银行手续费,ATM的链表,账户的链表。
实物类银联:
属性是银行的链表。
实物类中间没有什么算法和数据交互,主要是geter,seter。但是可以从实物类的属性看的出来各个类之间的关系。
那么,拥有卡号如何得到对应的账户呢?我们聚焦Account()类的一个静态方法getAmountbyCardNO(String cardNo):
静态方法,通常使用与数据全部出自参数的情况下,在这里,在构造迭代器的时候Accout直接用了静态的list
接下来是业务类validateData():
主要作用是判断数据的合法性,同时返回card或者ATM。
其中的第一个方法getCardByCardNo():
是一个静态方法,得到了银联就等于得到所有的数据,自然可以遍历得到card。另外一个得到ATM机的方法的细节类似。
接下来是业务类getBalance():
这个类感觉也可以写成上面validateData()类似的结构,只要一个静态的方法,传入参数就可以了。
接下来就是所有类当中的核心了业务类withdraw():
其属性有银联,和各种用户输入的数据。
这是很妙的,构造器的妙用,可以在构造类的时候运行,使代码更加简洁。在第538行的使用卡号得到card在前面validatedata进行了详细的分析。553,行,利用卡号得到账户,在类Account中详细分析了。
第579-585行计算了贷款手续费
在第588到598行进行了贷款是否超出的校验。我将可以取款理解为目前账户余额和可以透支余额的和为最大可取出的钱。只要这个数值小于取出的钱加上各种手续费,那么就是合法的。
至此,所有的类,流程都分析完毕,只剩Main():
Main里面是对银联的初始化
和对用户输入的简单处理,非常喜欢老师的主函数,因为除了读入输入,核心代码就147,148两行。
类图:
三, 踩坑心得
1、每次写博客的时候总会觉得,其实这道题也没有那么难,只要把类理清楚了不是很简单吗?但其实,有很多时候,仅仅是因为一个很简单的错误,要去找半天才可以发现的了,哪怕只是因为一下子粗心了。所以我在写代码的时候要更加仔细,不要写个大概然后再满世界找错误,要踏踏实实的,就像类里的每一个方法一样,一次只做一件事情,但是哪一件事情一定会做好,无数个小小的成功,终将实现整个代码的成功。
2、我写代码的时候,发现我的system.out报错,我就挺纳闷的,后来才知道是上一个方法写了类名,写了点,没写方法名。
3.在遍历链表的时候使用for each如果要删除链表内容的时候,会出问题。那就是链表的最后一个不会被遍历到,因为你删除了之后链表长度改变了,反正我是这么理解的,要使用迭代器来遍历这个链表或者goto语句来解决这个问题。
四,改进建议
1.我对静态类十分的不敏感,因为用的少,也因为完全可以被普通的类替代(现阶段),但我承认它的简洁和高效。因此要训练自己使用
2.泛型容器只知道ArrayList,同时ArrayList里面还有相当多的api我都不知道,自然也没有使用过,实践出真知。
五,总结:
总的来说,对数据之间的结构关系的理解尚待提高,对抽象类,接口的作用,应用环境需要加深理解。初步学习了有较复杂数据的数据处理方式,链表的使用。没有对除我自身之外的东西有任何意见。
以上是关于第三次博客作业的主要内容,如果未能解决你的问题,请参考以下文章