1.前言
这应该是本学期最后一次写作业总结了吧。总体来说,对作业的节奏也差不多掌握了,作业做起来的效率也更高了。虽然和之前的作业一样,作业中都要用到新的知识,但是相比之前,更加懂得了如何利用工具以及资料。虽然之间卡过壳,但总体而言,这几次作业还算完成的比较好。
2.作业过程总结
相比前两个单元,此单元的三次作业每次作业只有一道题。做题目没有了像之前那样的优先级,而是全程专注一道题。作业九则是通过雨刷程序功能扩展设计考察对类的封装、继承、多态的掌握度,作业十是通过 统计Java程序中关键词的出现次数考察对工具类List、Set或Map的掌握程度,作业十一则是设计表达式求值的程序,考察对栈的使用,并检验自己之前对正则表达式的掌握程度。总的来说,三次作业考察的重点是并列的,但都需要有之前学到的基础知识。通过这几次作业,对面向对象以及其基本原则有了更深的理解。
作业九刚开始看题目的时候感觉整体不难,但是仔细一想,需要在继承与组合的方法之间斟酌,是自己写出的程序能够使得程序在符合单一职责原则、迪米特法则、合成复用原则的基础上具有良好的扩展性(开-闭原则)、里氏代换原则、接口隔离原则及依赖 倒转原则。将题目写出来问题不大,但是如何使代码实现要求很难。我开始使用了继承的方法,但是因为子类要实现父类的方法,使得代码写到很长。我开始尝试去网上找一些例题,查找了一些组合的方法来解决问题。
作业十给人一种很简单的感觉,但实际却不简单,刚开始做的时候觉得这是到用正则表达式匹配,然后返回匹配正确次数的题目。但开始写主函数代码的时候,就碰到了问题。如何输入数据呢?是一行一行输还是整体用一个StringBuilder类型的参数将整体接收呢?如何判断输入的数据是否为源代码呢,遇到多行注释该如何跳过呢?诸如此类的很多问题,这个题目在细节上处理很麻烦。第一次的时候是直接用一个StringBuilder类型的参数将整体接收,发现在遇到单行注释的时候很难讲数据处理,就改为了一行一行输入,并在每行结尾加上换行符作为每一行结束的标志,通过换行符将数据切割成字符串数组,对每个字符串进行正则匹配,在每一行遇到单行换行符后直接跳过字符串后面的数据转而匹配下一行的数据,在遇到多行注释时,同理跳过知道遇到下一个注释符是继续匹配。因为TreeMap可以自动排序,所以选择TreeMap来装载得到的数据。因为53个关键词是不重复的,而关键词出现的次数是可以重复的,所以关键词为key,出现的次数对应value。本题存在疏漏,即题目测试未给出题目所测的53个关键字是以什么来排序的。而是叫我们去网上找,但是网上找的53个关键字的先后顺序是不一样的,我开始以为是按拼音来排序的,不管怎么做,正确的测试点只能过一个。看到有网站上写到53个字也是按拼音排的,唯一不同的是它将null放在了末尾,后来我尝试按这种方法排序,结果大部分测试点都过了。最后一个测试点过不了,至少我到最后都不知道最后一个测试点测的是什么数据。
作业十一的表达式求值,则需要用到自己完全没有接触过的知识,栈。开始基本上完全不知道栈是如何使用的,学着网上的一些例题和相关资料才有了一个大致的轮廓。大致思路是通过用一个栈来装数字,一个栈用来装符号,通过设定符号的优先级,来对数据进行计算。大致思路是将输入的字符串传入到一个字符数组中去,然后对字符数组遍历,用准备好的两个栈,分别来装载数字和字符,当输入比之前字符优先级的字符时,对之前的数据进行计算。开始经过测试的时候发现输入带括号的数据时很容易出错。通过设置一个条件语句,判断是否扫描到括号,若出现右括号,则从后往前计算,并不断删除已使用的符号,直到遇到左括号为止。此题考虑数据错误的情况有很多,需要逐一判断,总体上花了不少时间。
本单元的三次作业在大体上花的时间大概差不多,按顺序来三次作业大概花3:3:4的时间,总体上3次作业难度上总体难度相差不大。但是实际花的总时间应该能更短。每次拿到题目,一上来就是想到什么写什么,很容易卡壳。经过这几次的作业,我更加深入的理解面向对象的理念。在拿到一个题目时,应该先找出其中有哪些对象,然后通过一些方法将它们之间联系起来,形成一个大致的轮廓,同时也便于之后对疏漏的方法进行补充、对代码进行扩充。而不是想到什么写什么,这样到后面很容易出现自己用到的一大串的方法可能到后面用不上或者会影响代码的可拓展性而不得不舍弃。在添加新的方法时,应该考虑会不会影响代码的可扩展性和复用性,这样能够为之后增加新方法省下不少时间。
3.OO设计心得
①里氏替换原则:通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。在写代码时,经常会设计接口或抽象类,然后由子类来实现抽象方法,其中子类可以实现父类的抽象方法也必须完全实现父类的抽象方法,否则编译器就会报错。关键点在于子类不能覆盖父类的非抽象方法。如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。在继承父类属性和方法的同时,每个子类也都可以有自己的个性,在父类的基础上扩展自己的功能。当功能扩展时,子类尽量不要重写父类的方法,而是另写一个方法。
②依赖倒置原则:依赖倒置原则的包含如下的三层含义:高层模块不应该依赖低层模块,两者都应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象。打个比方奶茶店卖各种各样的奶茶,奶茶店就是高层模块,各种各样味道的奶茶就是低层模块。当我们想到奶茶这个名词时,我们会想到,奶茶店卖奶茶,奶茶有冰镇奶茶,酸奶等这类具体的东西。奶茶就好比一个由各种各样奶茶共享的接口,而奶茶店也依赖奶茶这个抽象类。
③接口隔离原则:通俗来理解就是,不要在一个接口里面放很多的方法,这样会显得这个类很臃肿不堪,而且后续维护与扩展也十分麻烦。接口尽量细化,一个接口对应一个功能模块,同时接口里面的方法应该尽可能的少,使接口更加轻便灵活。
④类设计心得:在拿到题目后,应先找出题目中的对象,通过构造方法使他们之间产生联系,一开始就要构造一个大致框架,把几个大模块设计成类,遵循单一职责原则和合成复用原则,并注意考虑其可扩展性和复用性,多使用接口、抽象类、多态等技术来设计类。尽量使用组合而不是继承。类与类之间可通过关联,聚合,依赖等关系来实现代码的复用,从而提高功能执行的效率。
4.测试的理解与实践
测试对于编码质量的重要性:测试能够极大的减少代码的错误以及漏洞,同时它还能够提醒写代码的人对运行时间过长冗杂的部分进行方法的改进。只要是提交的代码便会有错误的可能,而测试正是减少这些错误的最好的工具。测试还能够检测代码的效率,是否存在冗长多余的部分,通过测试可以提高代码的质量。
只有不断的练习,才能熟能生巧。通过练习,才能真正的将所学的知识运用起来,才能更加深入的理解,更好的掌握新知识。
5.课程收获
通过本单元的学习,我对类的封装、继承、多态,抽象类,接口的使用有了更深刻的认识,基本上已经能过熟练使用。加强了我对工具类List、Set或Map的认识,学会使用栈来解决题目。通过这几次作业,我认识到自己的不足,更能深刻体会学无止境这一道理,只有通过不断地学习,懂得东西才会更多,只有多动手,才能更加清楚发现自己的问题所在,加油。
6.对课程的建议
每次的作业总是和上课所学的知识不能紧密联系,上课所讲的进度每次都要比作业超前,以至于每次做实验时都要重新捡起以前的知识,这样要花费更多的时间。希望以后讲课能对标上作业,也希望老师可以带领我们多多练习,让学生也能看看老师是如何解题的。