第二次博客作业

 

 目录

  对作业的前言

  设计和分析

  踩坑心得

  改进建议

  总结

 

  前言:

      这是第二次博客作业,内容是对题目集的456次的分析总结反思。题量比较前面三次作业来说有所增加,难度有所减少,很喜欢这种学习有成就的驾驭感。在题目集四:主要考察了正则表达式,聚合。题目集五:主要考察了排序,Map的使用,另外一种聚合的形式。题目集六:考察继承的多态,接口的使用。

 

  设计与分析:

      ①  题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较

 

  这是题目集4的类 

 

  这是题目集五的类图:

 

 

  这两者很明显都是聚合设计,我简单描述一下两种集合讲讲其中的逻辑:

  题目集4(7-2),类图①。这道题目中DateUtil是一个业务类,它负责所有的实物类的数据交互,并且实现流程和实现关于日期的操作和方法。实物类的定义是这样的,Day有两个属性,日期value和月这个类,月有两个属性value和年这个类,年有一个属性value。所以我们发现一个具体日期,是从Day开始的链式的一串。因此我们在DateUtil中要使用年份的值的时候需要这样调用: day.getMonth().getYear().validate()。如果是要使用有关于年份的方法要这样调用:day.getMonth().getYear().validate().ifleapyear();我们很容易发现,几乎很多地方要使用方法,都要一长条代码才能调用得到。

  题目集5(7-4),类图②。 这道题中DateUtil是一个业务类,也是负责数据交互,流程,方法实现的。但是这一道题的形态和上题有很大不同。实物类的分别是Day,Month , year三个类分别是日书,月份,年份。各自的方法放在自己的类内。它们之间的关联很少。我们在DateUtil中使用

  简单讲讲几个核心算法:(这里也有两种不同聚合的体现)

    1.求后n天的日期

 

      (这一段是返回后n天的日期的代码,其本质是一天一天向后找遇到日期数大于本月最大日的时候进月(124-135行),月份大于12的时候进年(136-143行))

      (其优化点在于,已经通过循环判断将年份先进行计算,将循环次数大大压缩(107-119行))

 

    2.求前n天的日期。

 

        (注意第100行,这是链状的常见状态,如果要调用某个方法,或者要更改某个值,常常需要经过多次调用)

       (这一段是返回前n天的日期的代码,其本质是一天一天向前找遇到日期数小于一的时候退月(91-95行),月份小于一的时候退年(96-100行))

  3.计算两天之间的日数。计算个日期到0000年 1月 1 日的天数相减

 

 

       (总体逻辑就是按照年份进行计算天数(211-217),然后每月算天数218-236,最后加上每日的天数)

工具比较:

集合一:

 

  总行数: 411

  最大复杂的方法,DateUtil.getDaysofDayes()

  最大复杂度:21

  最大圈复杂度:8

  平均圈复杂度:4

 聚合二:

  总行数: 394(略胜)

  最大复杂的方法,DateUtil.getDaysofDayes()

  最大复杂度:21

  最大圈复杂度:7(胜)

  平均圈复杂度:3(胜)

  很容易发现平均最大圈复杂度超出了合适范围,最复杂方法复杂度超出合适范围。这个平均值说明自身水平还有待提高

  (乱码原因:类的名字使用了中文,这是不好的)

 

 

 

 

具体比较

  1开发方面 :

    链状:逻辑不如网状清晰,debug时很困难,因为是嵌套的关系,如果想同时追踪多个数据有些循环debug是不可避免。

    网状:更加符合人的思维方式。分开的类,各自的方法,debug很舒服。

  2耦合性:

    链状:各个实物类交错在一起。耦合性高

    网状:各个实物类分开,统一到DateUtil类中进行数据交互,耦合性低。

  3可复用方面:

    链状:各个实物类交错在一起。可复用率低,复用难度高。

    网状:各个类分开,可复用率高,复用难度低。

  4代码效率:

    链状:要实现一个方法,需要在所有类之中反复调用,效率低下。

    网状:避免了不需要的调用。

    5封装性:

    链状:封装性极好。

    网状:封装性较好。

 

 

 

  ②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)

 

  题目集四(7-3)这道题明确了要使用继承,如圆形(circle)方型(rectangle)继承图案(shape),球(boll)继承圆形(circle)。

  设计上:父类必须有子类的共有特征,所以他们共有的特点就是都可以求面积,所以父类的方法就是求面积(getArea())。

  

 

 

  每个子类的面积公式是不一样的,所以要对求面积的方法进行重写,

  每个子类都有自己独特的属性,所以需要重载。

 

  如下是Rectangle类的部分代码,体现出了重载和重写。

  …………

 

  子类也能有子类,就是再一个子类,但是它和上一级子类是一样的,只不过是又多了自己的一些方法。具体例子是box类,是rectangle的子类。它具有getArea方法,同时它也多出来求体积的方法。

 

  如下是其部分代码,体现出它重载,重写,新方法。(类的一部分)

  

  不难发现,父类是共性,子类是有特点的,不严谨的说子类的方法大于等于父类,事实也是如此。

 

如下是分析:

 

 

  总行数: 170(略胜)

  最大复杂的方法,Ball.getvolume()

  最大复杂度:8

  最大圈复杂度:3(胜)

  平均圈复杂度:1.7(胜)

  (乱码原因:类的名字使用了中文,这是不好的)

 

 

  题目集6(7-5)

  这道题重点是抽象类。

  在csdn上浏览有人如是说道:子类最好继承与抽象类。

  当然实体类依然可以做父类,但是没有必要。抽象类在我的眼里更像一种规范。是所有子类都必须遵从的规范。抽象类的高度抽象也能使编程更加具有调理,并且不会遗忘重要的特点。在这道题中:

  我的抽象类是shape,它只有签名,它提醒我,你的所有类都必须有两个方法,求面积(getArea)和求其是否合法(validate())。

  

 

 

  所以我再它的子类(Circl)(rectangle)(triganle)的方法里进行了复写。

 

  这里我只举例rectangle类。

   

 

 

   上图就是类图,清晰明了的展示了,三个实物类继承与一个抽象实物类。

 

 

如下是结合分析器分析:

 

 

  总行数: 206

  最大复杂的方法,Triganle.validate()

  最大复杂度:5

  最大圈复杂度:5

  平均圈复杂度:2

  总体来说最大平均复杂度还是高了

  (乱码原因:类的名字使用了中文,这是不好的)

 

 

  题目集6(7-6)

  这道题的重点是接口。

  接口有点像抽象类,但仅仅是形态像,没有方法细节,只有签名。也不能直接生成对象,只能有子类继承后才能生成对象。他和抽象类最重要的区别还是它的功能。接口的侧重点是特殊点,抽象类父类的侧重点是相同点。一个类可以继承与多个接口,但是只能是一个抽象类的子类。抽象类可以有方法细节,但是接口不能有。

  讲讲此题,接口和多态性。很明显的,两个类,Circ Rectang。都必须要继承getArea这个接口。但是他们的面积公式显然不同,此时,在每个类的定义中要用@Override来重写getArea的方法。

  很容易发现,两个方法的名字相同。但是引用的时候可以看出。调用getArea的时候,使用的公式由调用者的类来决定。这就体现出多态了

  此题我的接口是:

 

 

 

  我的子类:(以circle为例,其他子类的方法结构大同小异)

    

 

 

                                               上面就是我的类图,清晰的看出两个子类继承与接口

      (我很是希望自己的代码都能简洁如此)

如下是结合分析软件分析:

 

 

  总行数: 61

  最大复杂度:1

  最大圈复杂度:3

  平均圈复杂度:1.3

 

  ②    对三次题目集中用到的正则表达式技术的分析总结

 

  挨个分析:

  首先是水文如题(图)

对字符串的处理,查找是否合法,很明显的要使用正则表达式,我讲讲自己如何处理。

处理过程:1:一行一行读入,每次读入除去首尾空格,存入字符串数组(31,37行)

 

 

 

                2:按照“|”个数判断是否有“|”存在问题(上图40行)

                3:将字符串以“|”分割(40行),将数据间的空格删除(47-49)。再拼回去(50-57)

 

 

 

 

 

 

 

       (运用了StringBuilder,split,trim,append等方法,我觉得可以简化,因为多出来很多循环)

              5:按照位置进行正则表达式匹配。

 

 

     (temp1[x],x是我已经分离出好的字符对应的组,validatexxxxxx是不同的判断的方法,分别判断各个位置的数据合法性如下是各个方法的内容细节)

 

  我匹配开度的代码:

 

 结合分析软件分析:

 

  总行数: 367(行数在再不是炫耀的东西了)

  最大复杂度:17

  最大圈复杂度:5

  平均圈复杂度:2.35

  最大圈复杂度才5着实让我觉得欢喜。

  在下面那个圆圆的雷达图可以看出,最大复杂超出合适范围,仔细看后是检测日期是否合法的方法过于复杂。原因是使用正则表达式然后group分组,然后提取进行数据比对分析。如果使用了java中自带的time处理方法一定会减少不少的复杂度。

  (乱码原因:类的名字使用了中文,这是不好的)

 

 

  匹配水位的代码:结构和上面一致,因此我只写正则表达式   String regex = "(\\d+)(\\.\\d{1,3})?";

  匹配整个数据的代码:java.util.regex.Pattern p = java.util.regex.Pattern.compile

  ("(\\d+/\\d{1,2}/\\d{1,2} \\d{1,2}:\\d{1,2})\\|(\\d+(?:\\.\\d{1,3})?)\\|(\\d+(?:\\.\\d{1,3})?)\\|(\\d{1}.\\d{1,2})[ ]*/[ ]*(\\d{1}.\\d{1,2})\\|(\\d+(?:\\.\\d{1,3})?)");

        6.将判断结果返回即可(简单就不放源码了)

 

  其他正则表达式的题目:

    匹配qq号:java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\d{5,15}");

    后来匹配验证码:Pattern p = Pattern.compile("[\\d\\w]{4}");

  使用心得:1.正则表达式对于输入内容的是否合法判断起到至关重要的作用。它能避免很多if-else语句,大大减少代码的长度和运行时间复杂度等等。比如我要匹配验证码,简单的[\\d\\w]{4}就蕴含大量信息,如果要使用if-else去写可能随随便便就超过60行了。

     2.正则表达式好用的很,但是写正则表达式是痛苦的。但是没有任何理由的肯定要学好,这么强大的工具不学以后会让我更累。我写正则表达式强调与每个数据的捕获组一定要明确,因为group函数是真的很好用。可以提取一大串字符串中需要的东西。很关键

③    题目集5(7-4)中Java集合框架应用的分析总结

 

  这道题我没有看到要求时,选择了一个很不难的算法。在正则表达式

  成功删除不需要的部分后,可以写一个循环嵌套循环,将每个单词和库里的单词进行比对。

  后来才知道要使用map类,hashmap和trmap我选择了后者,因为它会把key进行排序这样我再输出的时候只需要将value是零的key排除即可。输出的就是

  Map我觉得在特定的情况下非常实用。因为它提供了一种对应关系的储存方式,和生活的很多情况息息相关,比如学号和姓名或者。同时它的key和value都可以自定义类型,使用起来很舒服。同时它也提供了多种方法。

   借题目集5(7-4)好好讲讲map

  1.运用正则表达式等方式将得到的字符串进行处理。

 

     (第22行:匹配正则表达式,使用group函数,得到“//”前的所有字符)

    (第26行:将得到的字符出去首尾空格,统一为一个空格,方便后面进行分割)

  2.利用正则表达式,除去双引号之间的字符(39行),除去“/* ..... */”(41行)。

 

 

   

  3.将符号除去(43,44行),以空格为界限,将字符串分割为一个一个单词(49行)。

 

 

 

  4.创建,初始化Treemap。

 

 

     (一个小小循环)

  5.循环,将得到的单词与key进行比对,如果匹配则key对应的value加一。

 

 

   6.利用构造器的遍历。

  上题囊括了Map函数的构造,初始化,通过key访问value,更改value,比对key,以及遍历Map值得回味。

 

结合分析软件分析:

 

  总行数: 87

  最大复杂度:0

  最大圈复杂度:4

  平均圈复杂度:2.24

 

 

  踩坑心得:

  1.  0真的是一个很特别的存在,小于0和小于等于零真的搞死了我很多次。还有就是正则表达式的使用实在是非常菜,很多想表达的东西表达不出来,自己的一些思想我觉得也可以改变,比如我很喜欢的模式是对数据进行预处理,之后在进行正则表达式的匹配。这当然是好的,但是正则表达式是很厉害的东西,相比较与提前处理字符串再进行匹配,为何不能一步到位呢?这样能大幅度减少代码量,复杂度。说实话写起来也让自己舒服。

  2.还有一点就是不仔细审题,啊,老问题了。也到不是没看题,是没看到题会怎么出问题,没有先见性。很多问题在看题目的时候就应该注意到,会不会有这种输入?这样输入的话我的程序应该怎么避免崩溃?等等。总是等到真正交代码的时候,明明看似可以完成任务的代码,在测试点面前被蹂躏,我人就不好了。然后又根据提示在我的代码上缝缝补补。搞得我的代码虽然有调理性,但是写的稀碎,一看就是之后急急忙忙补上去的。这样好吗?这样不好

 

 

 

  改进建议:

  我建议自己的代码可以尽量使用新东西。一是减少代码量,二也能练习一下新东西。我建议自己完善自己的类功能,尽量写的完美一点,万一那天拿出来稍微改改就能用了,那多舒服。我建议自己多学学正则表达式,这玩意是真的好用。有人如是说道,没有正则表达式匹配不到的东西,我还到不了那种境界,我只希望自己可以吧老师的题目给它好好匹配出来

 

 

 

 

 

总结:

  1.在这一阶段我学到了正则表达式,字符串处理,抽象类,接口,继承的使用,进一步理解了多态的含义。我的研究方向应该是如改进建议所说的东西。

  2.令人开心的是我的最大圈复杂度终于减下来了。然后每个类的圈复杂度也下来了。

  3.在写博客期间我还参加了学校创新设计班的选拔考试,太惨了。发现很多时候我都依托与自己以前写下的代码,很多该记下来的东西都没记得比如字符串转换为整形,字符串子串的定位。

  改进建议:我认为这一阶段,尤其是题目集六的内容,节奏,难度十分完美。有练习,有新东西,难度适合,学到新东西,有成就感,我发现自己愿意花更多时间学习新语法,愿意去写一些自己感兴趣的东西。

 

posted @ 2021-04-30 09:39    阅读(105)  评论(0)    收藏  举报