2019 - OO第二单元作业总结

一、设计策略分析与总结


 

  • 第一次作业:设计策略很简单,共有四个类:Main、InputRequest、Scheduler、Elevator。其中InputRequest不断把输入进来的请求传给Scheduler,保存在一个请求队列中;对于Elevator,每执行完一条请求就向Scheduler拿一条新的请求,直到输入结束且请求队列为空。
  • 第二次作业:从设计角度上进行了有关捎带功能的完善,仍然是上述四个类。增加的功能有:电梯类在每到达一层时都要进行一个OffOn()判断。这个函数的作用是:先通过Scheduler搜索是否有能够捎带的请求(判断能否捎带的元素有:乘客是否在这一层、这条请求的运行方向是否与当前电梯的运行方向一致),然后判断是否有要下电梯和要上电梯的乘客,若有,则把先下后上,这时根据先前的判读哪能够把要捎带的乘客也安排进入电梯。同样的,线程结束的标志为输入结束且请求队列为空。
  • 第三次作业:仍然是上述四个类。从功能上相较于第二次增加了关于乘客数量和停靠楼层的限制。Scheduler中的请求队列由一个变成了两个,当InputRequest把输入进来的请求传给Scheduler时,由Scheduler对于这个请求进行拆分,若可以直达,保存进que这个队列中,若不能直达则分割成两个请求分别存入到que和queExchange这两个队列中。这里的两个队列的不同之处在于,que中的请求是当下可以被执行的,而queExchange中的请求是针对需要换乘的请求在第一阶段完成之后才会被执行的。Elevator除了在可停靠楼层、准乘人数、运行时间上稍加 限制之外,其他功能基本不变,只是在乘客出电梯后把相应换乘的后半部分请求从queExchange中拿出来放入que中。这样就解决了多个电梯线程的执行问题。

二、基于度量对程序结构的分析


 

2.1 第一次作业

      2.1.1 类图

 2.1.2 度量分析

    

    

     2.1.3 设计原则

    开放封闭原则:可拓展性不强。

     2.1.4 总体分析

    第一次作业实现上比较简单,除了可扩展性不强之外没有什么很大的问题。

    2.2 第二次作业

      2.2.1 类图

    

      2.2.2 度量分析

    

    

    

    

      2.2.3 设计原则

    Single Responsibility Principle:电梯类设计冗杂。

    Open Close Principle:有了一定的可扩展性。

      2.2.4 总体分析

  这次作业虽然基本实现了捎带的调度但是从性能上来讲基本没有得到很高的分数,原因应该是调度策略不够优异。同时在设计上有一定程度的冗余,具体表现为一个类中的方法过多,这也是设计上的一个缺点。优点在于对下一次多部电梯的设计打下了基础。

 

    2.3 第三次作业

      2.3.1 类图

    

      2.3.2 度量分析

    

    

    

    

      2.3.3 设计原则

    Single Responsibility Principle:电梯类设计冗杂,调度器设计冗杂。

      2.3.4 总体分析

  本次作业基本实现了对上次作业代码的复现,并在此基础上添加了一些必要的功能。这一次我基本保证了正确性,由于还是沿用上次作业实现的调度策略,在性能上还有很大的提高空间。同时由于功能以及限制的增加,类冗杂的情况进一步加重,这是后期我需要学习优化的重点。

 

三、bug分析


 

本单元的电梯作业基本上不会出现算法上的Bug,我找出的自己的bug主要体现在线程方面:

  • 第一次:无bug;
  • 第二次:bug体现在判断上下电梯方面,出现了一个人还没有上电梯,却提前下电梯的情况;
  • 第三次:由于有多个电梯线程,所以在请求的竞争上由于”锁“的原因产生了一些bug;另一方面,由于我把需换乘请求分割成了两个部分,所以在判断电梯线程结束标志时不能仅局限于输入完毕且que队列中无请求,还应考虑queExchange队列中的请求情况。在解决这个问题之前我的电梯会出现提前终止运行的情况,我在找出这个bug方面耗费了一定的时间。

四、互测分析


 

这次的互测与以往不同,不仅需要数据上的考量,还应考虑时间问题。我并没能完全掌握实现按时间投放请求的方法,所以在本次互测中参与程度不高。

五、心得体会


  (一)线程安全

我在本单元中遇到的有关线程安全的问题主要有

  • 如何使电梯线程在合适的时候结束:在这里我在Scheduler中设置了一个布尔变量isEmpty用来标识输入是否结束;当输入已经结束且请求队列中没有要处理的请求时,才结束电梯线程(对于第三次作业的特殊情况已在上述提到,在此不做赘述);
  • 如何合理分配请求使得不会出现”电梯吃人“、”电梯造人“等现象:把请求队列交由Scheduler管理,在第三次作业中,还有把请求传递给电梯保存这样的操作,这就保证了一条请求仅会被一个电梯执行。

同时关于wait()和notifyAll()的使用以及synchronized的使用方法的学习也使我对于几个线程同时运行时会出现的现象有了更深层次的了解,正确掌握了这几个知识点之后,就能基本解决多线程问题。

  (二)设计原则

  • 单一责任原则:有关于这个原则,我的代码存在着很大的问题,用的类过于少,使得每个类中的方法过多,这就导致了职责分配不清,多种职责混杂在一起,不利于之后对项目的管理,同时阅读体验也不够好。
  • 开放封闭原则:其中第一次作业由于比较简单,没有过多考虑性能问题,代码属于硬编码;在后两次作业中一定程度上实现了继承,这也算是我对于继承代码的优点的初次体验。

猜你喜欢

转载自www.cnblogs.com/lsw-CS-2019/p/10743248.html