面向对象第一单元总结

面向对象第一单元总结

第一次作业

设计思路

  第一次的作业要求相对简单,只需要完成对幂函数的简单多项式求导。核心的思路是:取出表达式中的每一项,对每一项单独的分析,存储起来求导后再合并。具体的处理是首先判断输入的字符串是否符合规则,不符合规则直接报错。如果符合规则的话,则进行预处理。预处理需要做的事情有两件:1.将字符串中的空白字符(空格和\t)去掉;2.判断整个表达式最前面是否有正负号,如果没有则添加一个正号。这里需要解释预处理的第二点,添加这个正号是为了符合表达式中每一个项的一般形式(也就是每一项前面必然至少有一个正或者负号)。然后通过正则表达式匹配每一项,将表达式中的每一项取出来,再具体的判断分析。至于类的设置,显然是有一个表达式类,然后有一个项类,但是由于每个项的因子并不复杂,而且只包含幂函数这一种,设计时并没有考虑到可扩展性,将项和因子杂糅在一起。表达式类中有对表达式进行处理的各种方法,主要有获得表达式的方法,判断表达式输入是否正确,表达式预处理,打印表达式,以及合并表达式。而项类当中则主要是对项的求导,以及设置和获得项的参数的方法。

程序处理流程:

UML类图

复杂度分析

  这里的main和printTermList两个方法都极差,多项都红色了,这是这两个方法比较杂糅,没有将有的板块独立出来,所以比较冗杂。

BUG修改、程序的不足

BUG:设计的时候没有考虑到系数和指数过大的可能,只是简单的使用了int类型,导致最后强侧的时候,一半的测试点都溢出了。的确是考虑问题上的疏忽,尽管题目在有的地方极力暗示可能普通的int甚至long类型不够用,但是我还是忽视了这个问题。在后来更改为BigInteger之后,发现BigInteger是非常好用而且安全的。

BUG:在讨论的时候,有的人似乎和我的思路并不相同,并不是用正则表达式去一项一项的匹配,而是整个表达式一起匹配了,这样如果对匹配模式没有限制,使用默认的贪婪匹配的话,在项数较多的时候,可能会导致栈溢出,而产生异常。

不足:并没有将项和因子的概念区分开,因为第一次作业简单,所以这里的影响并不大,但是降低了程序的可扩展性,以及感觉上不是那么的对象分明。这里设置的项的属性,更像是后面的幂函数因子。

第二次作业

设计思路

  第二次的作业在要求上添加了三角函数因子,并且需要支持对乘法的求导。核心思路和第一次作业一样,也是取出每一项,再对每一项进行分析,求导,再合并。具体的处理类似,判断输入是否符合规则,然后进行预处理,这里的预处理和第一次一样,然后通过正则表达式匹配每一项,将表达式中的每一项取出来,然后再通过String的方法split方法,将每一个因子分出来,判断他们的指数,最后存入项的参数中。遗憾的是,这里按道理来说应该是有一个项类,有三个因子类,但是这里每一个项的格式,必然是又幂函数,三角函数组成,以及我面向对象思想的不完善,所以只是采用了参数的方式来存储幂函数的指数,三角函数的指数,以及常数因子。这里是很不面向对象的。然后再调用一个求导方法求导,将求导结果放入一个列表中,便于后续的处理。这次的作业优化和第一次的更难,采用了hashmap的方式,通过每个项的参数来进行查找合并,处理普通的合并指数都相同的情况,还对sin^2+cos^2为1的类型进行了合并,但是似乎合并的效果并不尽如人意。这里依然只设计了两个类,表达式类和项类。如果说第一次只设计两个类是因为较为简单,还情有可原,那第二次就单纯的是面向对象的思想没有根深蒂固。程序处理的流程和第一次类似,就不再给出。

UML类图

  从类图中可以看到,Expression中的方法非常多,非常冗杂,这是初次设计比较复杂的结构,不是很熟练的缘故,将很多本来应该在Term中的方法也写到了Expression中,这样虽然没有错误,但是逻辑上来说,这是不对的,是很不面向对象的。

复杂度分析

BUG修改、程序的不足

不足:设计上的不足在于,并没有很好的利用面向对象的思想,将表达式,项,因子的概念给区分开,导致程序比较杂糅,方法放置的位置也不太对,感觉更像是c编程的思路,而不是java面向对象的思路。

不足:对访问控制理解不够,应该将类的成员变量设置为私有,再设置相关的方法对其进行修改和访问的思想并不是很熟悉,导致成员变量的设置和访问比较混乱。

不足:对于最后表达式的优化,一开始是想到了可以用1-sin^2 = cos^2 ,1-cos^2 = sin^2 ,sin^2+cos^2 = 1来进行处理,但是由于我一开始设计成了,每进行一次合并,便会置一个标志,这个标志会让程序再遍历一遍每一个项,但是实际上,如果对系数不同的也强行进行合并,会导致这个循环无限进行下去(这里的系数不同指的是,类似于3sin^2+cos^2 = 1 + 2 * sin^2这种类型),没有思考太清楚,最后就之采用了第三个公式进行合并处理,导致最后的结果也不太理想。

第三次作业

设计思路

  第三次作业除了前面的要求外,还要求要能够支持三角函数内部的嵌套。基本思路和前两次一样,也是取出每一项,对每一项进行分析,求导再合并。和前面不一样的在于这次的预处理,除了前面提到的去掉空白字符和添加正负号以外,还进行的处理有:1.将最外层的sin和cos的括号换为#;2.将最外层的乘号换为@符号。换为#是为了方便正则表达式匹配,将项能够分出来,而改为@符号是为了获取到每一项的时候,能够快速的通过split将每一个因子分裂开。对于每一项的处理,就是利用split将每个因子分开,然后再调用具体的因子的方法进行分析。最后再合并起来,依次一层一层的返回。这一次设置了表达式类,项类,和因子类,具体的因子类,继承于抽象类factor。

UML类图

  根据设计,ExprFactor,NumFactor,PowerFactro,CosFactor,SinFactor这五个类均是继承于Factor这个抽象类,重写了Factor中的抽象方法求导,以及写了每个类自己的构造方法。表达式类和项类主要就是调用因子类来进行具体的处理,以及处理后的合并等。

复杂度分析

  从里面可以看到,v(G)变红的两个方法是preProcess和termDerive,这两个当中进行了比较多的if嵌套,或者是循环当中嵌套if语句,导致这两个当中的这一项变红。前者是因为处理的时候,遇到多个括号,需要判断括号和乘号是否是在最外层,所以导致判断的嵌套比较多。然后是第二个,第二个是因为我们这次作业里包含的因子比较多,判断因子具体是哪一个因子,应该调用什么方法的时候,用了比较多的判断,这里也许可以尝试改成switch语句,可能可以降低一点这个值。

BUG修改、程序的不足

BUG:对于嵌套因子的理解不够,sin和cos中嵌套的因子应该要么是表达式因子,表达式因子需要一对额外的括号,要么是单独的一个因子。一开始对于sin(x+10)类似于这样的内部是一个表达式因子的,虽然现实生活中这是正确的表达,但是在规则中这是不对的。

Applying Creational Pattern

  只是在第三次作业当中用到了继承,抽象和重写的机制。继承和抽象让我对第三次作业的类的设计思路更加清晰。其实按道理来说,如果第一次作业设计得当,通过适当的扩展,应该是能够很容易的包含进第三次作业的。但是显然作为面向对象的初级选手,并没有这样一种能力,教学组这样一步一步循序渐渐的方式大概也是在提醒我们应该多思考一些,让我们在以后的设计中,要有一定的预见性,让类的功能更加分明。

总结

  从设计上来看,从一开始类杂糅,嵌套过多,复杂度也也很差,到最后复杂度降低了很多,并且类的功能分明,大概是设计和写代码这一部分有了一定的进步,以及对java面向对象思想的更加了解。最后一次写代码用到的继承,重写,抽象,对这些的实践也让我对他们有了更深入的了解。以及最后面try-catch的使用,让我对java的异常处理也有了一定的了解,但是对于throws exception等其它异常的用法还不是很了解,需要更加深入的了解学习。除此之外,对程序代码风格的规范让我也学习到了很多。规范的确能带来更多的便利。总的来说,这一个单元让我对面向对象和java语言有了初步的认识,更多的只是还需要慢慢通过这门课上或者是其它渠道去了解学习。

posted on 2019-03-27 13:27  没心的先生懒  阅读(134)  评论(0编辑  收藏  举报