面向对象设计与构造课程总结
初次接触java,感觉这门语言跟c++挺接近的。其实历史上这两门语言都是在一个时间发布的。但是写着写着才发现,两门语言的编程思路完全不同。c++的初学者可能还是通过c语言的思路来对内容进行的操作,而java所有操作都是对对象的操作。
在互测别人的代码的时候能看到明显的c语言痕迹。甚至有极端是一个main函数从头到尾的。(当然我自己写函数的时候也好不了太多。)c语言仍然对我们有很深的影响。
文中所使用的类图是使用eclipse插件 amaterasUML所自动生成。菱形箭头为类的实现。普通连接线为嵌套关系。
#第一次作业<多项式相加>
如果让我使用c或者c++实现多项式的相加的话,我会选择链表或者用数组模拟链表来实现。在java环境中,由于教师在开始规定不能使用链表(后来又更改为允许使用),因此创建了一个数组进行存储。
在第一次作业中,我创建了两个类:单项式类和多项式类。在多项式的要求中,总项数量不能超过1000.因此我就开设了1000长度的数组。因此在最后的压力测试中出现了数组越界的crash错误。在随后的作业中,我应该开更大的空间的数组,或者直接用链表ArrayList进行存储,这样可以有效防止溢出。
第一次作业类图如下
在类图中,polymonomial中实现了1000个数组长度的monomial。多项式类实现了加法与减法,单项式类实现了加法与减法。
在第一次作业中,我使用了正则表达式判断输入的合法化。java的正则表达式需要进行二次转义。例如匹配数字的\d是在正则表达式中匹配数字字符,在字符串中需要对右斜杠进行二次转义,即\\d.
总体而言第一次作业并不困难。但是思路上从面向过程编程转换到面向对象编程是一个挑战。其实在构造出面向过程编程的思路后,将不同的模块和函数重新组合成为类的函数,可以解决初期的不适应的问题。
#第二次作业<傻瓜电梯>
第二次作业的难点在于构造。
第二次作业的解决方案有两类思路:程序模拟与时间模拟。其中,指令模拟是读取所有的输入,并计算每一条指令的开始时间,结束时间。时间模拟为系统每0.5秒(电梯运行的最小时间单位)扫描一次当前状态,并更改状态。我在考虑的时候采用的指令模拟的方式。
指令模拟的思路较为简单。但是在后来的第三次作业捎带电梯会比较复杂。捎带电梯由于存在指令捎带问题,电梯的模拟会不友好。
时间模拟的思路更为简单。但是时间模拟的指令会出现运行时间长的问题。如果遍历最长的时间的话,理论运行时间可能为数小时。时间模拟可以使用加速的方法,即当长时间接受不到指令的情况下,进行长时间跳跃至下一个指令开始时间。我的部分同学在第二次作业改为第三次作业的过程中采用了这个方法。
关于输入匹配:
由于存在两个形式的输入,因此正则表达式的写法会比较复杂。
在我跟同学讨论的时候就思考如何用一个正则表达式匹配两种形式的输入。后来更改为匹配两次之后进行或运算。
此外,
别人的bug存在一些问题。10个字符的数字可能会产生int越界问题。因此使用long或者限制输入字符长度会比较合理。
在我自己的电梯中,使用的数组第i位是楼层-1.因此出现了请求同层判定错误。
类图说明:
输入的相关判定在main函数中完成。随后在main函数中实例化一个调度器schedual。调度器接受所有输入并进行计算。
电梯类接收request列表并进行运行,实现request请求。
#第三次作业<另一个傻瓜电梯>
在第三次作业的实现中,电梯需要捎带同向请求。在每次运行之前,需要预测该指令的结束时间。而这个预测的结束时间又随着添加的附带指令而变化。因此在之前的结构之中,我添加了楼层灯的标记,用来标记是否为同质指令。
在执行的过程中,需要对傻瓜电梯进行排序。为自定义request的排序过程,我重新定义了两个配需类的排序函数。见类图的右上角。
在继承的过程中,新的调度器的调度函数进行了函数的重载。