OO第二阶段Blog作业
一,前言
1,第二阶段三次题目集难度
相较于上一阶段难度略微增加,不过因为有了基础,这一阶段的题目写起来比上一次的更加得心应手了。由于其他同学的意见,每次的题量有所增加,不过增加的是一些简单的小题目,每次题目集的中心主要是放在一两道题目上。
2,题目集04
7-1 水文数据校验及处理
这道题主要是处理字符串并且对输入的字符串数据进行合法性检验,难点在于从字符串中提取数据以及对日期的合法性检测
7-2 日期问题面向对象设计
主要是利用聚合关系来设计年月日。
7-3 图形继承
利用类的继承来设计不同的图形
3,题目集05
7-4 统计Java程序中关键词的出现次数
应用集合框架的内容来解决问题
7-5 日期问题面向对象设计
上次题目集7-3类似,但用了另一种聚合设计来完成
题目集06
7-5 图形继承与多态
在上次题目集7-3基础上利用多态拓展了更多的功能
7-6 实现图形接口及多态性
在7-5的基础上优化设计,利用接口使不同的图形类具有相同方法的不同实现,优化代码结构。
二,设计与分析
1,题目集4(7-2)、题目集5(7-4)聚合设计的优劣比较
首先是各题目的类图和圈复杂度
题目集4(7-2)
类图

第一题的设计是将天当作月的一部分,月又当作年的一部分,以聚合的关系来设计的。
圈复杂度




除了主方法的圈复杂度较高以外,其他方法并不高
题目集5(7-4)
类图

这道题将Year, Month, Day作为DateUtil的一部分,依然是以聚合关系设计的
圈复杂度




与上一道题类似,由于主方法基本和上一道题一样,所以圈复杂度仍然比较高
分析
可以看出,两道题设计的不同在于Year, Month, Day之间的关系不同。第一题是聚合关系,而第二题三者之间没有直接关系,因此第一题的耦合度应该较高。
第一题的设计比较好的是在设计月份和天数增加和减少的方法时可以直接通过各自的属性(年,月)判断是否进位或退位,简化了问题。而第二题由于年月日没有直接关系,不能在设计月和天增加和减少的方法时判断是否进位或退位,因此每次调用月和天增加和减少的方法都要额外判断进退位,没有很好的简化问题。
2,题目集4(7-3)、题目集6(7-5、7-6)中图形继承设计的思路与技术运用
题目集4(7-3)
类图

Rectangle, Circle继承自Shape,Box继承自Rectangle,Ball继承自Circle。
圈复杂度

题目集6(7-5)
类图

和上一题类似Rectangle, Triangle, Circle继承自Shape,但Shape是抽象类,有一个抽象方法getArea()。
圈复杂度


题目集6(7-6)
类图

Rectangle, Circle有一个共同的接口GetArea。
圈复杂度



分析
第一题的设计只是用到了封装和继承,设计了Rectangle, Circle继承自Shape,Box继承自Rectangle,Ball继承自Circle。
第二题则将Shape设计成了抽象类,并运用了多态,使不同的形状统一了求面积的操作,优化了代码结构。
第三题用到了接口来表示一个求面积的操作,同样实现了多态。
虽然同是求面积,但是不同题目的设计体现出了不同技术的特性,我们可以通过封装隐藏具体的实现,用继承提高代码复用性,用多态使代码更灵活。
3,对三次题目集中用到的正则表达式技术的分析总结
三次题目集中用到了正则表达式来处理水文数据,检验QQ号,验证码和学号。
比如学号的检验:
要检验的学号要求:
对软件学院2020级同学学号进行校验,学号共八位,规则如下:
1、2位:入学年份后两位,例如20年
3、4位:学院代码,软件学院代码为20
5位:方向代码,例如1为软件工程,7为物联网
6位:班级序号
7、8位:学号(序号)
要求如下:
只针对2020级
其中软件工程专业班级分别为:202011-17、61,物联网工程专业班级为202071-202073,数据科学与大数据专业班级为202081-82
每个班级学号后两位为01-40
分析
设计能表示学号的正则表达式,可以将学号中不相关的部分拆开,然后实现每一部分,最后组合起来就得到了最终的表达式。
前四位固定为2020,五六位互相关联,七八位互相关联,因此可以分为三部分设计表达式。
根据规则设计出正则表达式"2020(1[1-7]|61|7[1-3]|8[1-2])(0[1-9]|[1-3][0-9]|40)"。
4,题目集5(7-4)中Java集合框架的应用
题目内容为统计Java程序中关键词的出现次数,在保存每一行的源代码,我用到了集合框架中的ArrayList,相当于动态数组,因为在输入时并不知道源代码的行数,因此用ArrayList更加方便。
三,踩坑心得
1. 引用类型的值改变
在题目集4(7-2)中,我曾试图用以下方法获取两个日期的相差天数
public int getDaysofDates(DateUtil date) {
int days = 0;
Day tmp;
//将date变成大值
if (this.compareDates(date)) {
tmp = date.getDay();
date.setDay(this.day);
this.day = tmp;
}
while(!this.equalTwoDates(date)) {
date.getDay().dayReduction();
days++;
}
return days;
}
这确实有效,因为这道题目只需要输出结果。
但是在题目集(7-5)中,我用同样的方法输出相差天数,结果却有些不对劲,因为这道题还要求输出原来的两个日期,在获取相差天数时原来传入方法中的日期被修改了,所以并不能继续输出原来的日期。这时我才想到在java中引用类型传递的是值的地址,因此如果在传入方法后修改了值,原来指向这个地址的所有对象的值都会被改变。
想要能获取原日期,要么想办法在方法中不改变值,要么在调用方法前就记录下原日期。这两种办法本质上是相同的,就是再克隆一个指向不同地址但值相同的对象。在网上查阅解决办法时,发现java有一个clone方法可以拷贝一个对象,但只是浅拷贝,对象内属性是引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存,因此还要重写clone方法。
四,改进建议
题目集5(7-4)统计Java程序中关键词的出现次数
在统计每个关键词出现次数时也可以用HashMap,将每个关键次和关键词的出现次数一一映射,由于当时没想太多,我只用了两个数组来保存关键词和出现次数。
题目集5(7-4)日期问题面向对象设计
正如上面分析,每次调用月和天增加和减少的方法都要额外判断进退位。
个人认为,有一个好的解决方法是将年月日的增减方法放在DateUtil里,因为天数和月份的增减操作不和月份,年份有关系。
五,总结
收获
这三次题目集涉及了很多面向对象的内容,在认真看过老师给出的类图设计后确实能掌握一些如何来设计一个程序的知识了,同时也能明显感到面向对象程序设计给编程带来的便利,相比于以前的代码,现在写出的代码在可读性,可拓展性上都有极大的提升,可以说受益匪浅。
建议
- 个人认为其实没有必要增加题量,应该保持少而精的原则,因为写简单的小题目实在是没有什么意思,我不认为时效比很高,最多就是给我们一点自信心罢了。私以为,体量大的题目才更能体现面向对象程序设计的好处,也更能锻炼我们的程序设计能力。
- 我发现题目集5(7-5)的数据好像有点问题,如果年份为一时减少或年份为负一时增加会将年份零计算在里面,但是很明显,现实上并没有公元零年,公元一年的前一年应该是公元前一年。

浙公网安备 33010602011771号