面向对象第二单元总结
第二单元的主要内容为电梯的优化控制。在本单元中,我们学习了 Java 的多线程操作,了解了多线程同步控制的方法。同时,对电梯的控制算法有了初步的了解。
多线程同步策略
在本单元中,为了提高性能,以及减少多线程控制时可能出现的死锁 bug,我采用了“尽量减少锁”的策略。在这个策略下,我将“加锁的对象”限制在类内部,不跨类使用锁;同时,在处理请求队列时,使用了 BlockingQueue 类,减少了需要锁的地方。
设计架构
在第一次作业中,只有一部电梯,需求较简单;但是考虑到后续可能会增加多部电梯,我仍然将整个架构拆分为两部分:调度器和电梯。其中,调度器负责在合适的时机向电梯分发任务,而电梯则根据每层楼的情况决定自身运动的是否开门。
在第二次作业中,增加了多个电梯的需求,故在第一次作业上进行扩展。首先,为了确定最佳的电梯,为电梯增加了仿真模式,可以在分配人之前准确判断分配给哪个电梯所需要的时间最少;然后,修改调度器行为,让它能够调用电梯仿真。
在第三次作业中,增加了换乘的需求。我的处理方式是,在请求传入的时候,使用简单的时长估计算法确定换乘的楼层,然后分级处理请求(如果需要换乘,就拆成两个请求处理)。这样达到了不错的效果。
三次作业中,强测分数逐渐递增,最后一次作业的分数在 99.3 分,说明调度算法的优化是恰当的。
扩展性
第三次作业的调度器采用的“模拟”策略,在现实生活场景(数据量不大的情况)下,几乎总是可以实现最优的分配策略。如果有其他需求,只需要修改电梯本身的代码,无需单独修改仿真器,就能实现较好的仿真。
SOLID 原则分析
S - 单一功能原则:本单元中,调度器和电梯职责分明、功能清晰,基本实现了单一功能原则。
O - 开闭原则:本单元由于需求修改较大,所以对代码的修改较多,没有实现开闭原则。
L - 里氏替换原则:本单元没有使用继承,所以无法讨论里氏替换原则。
I - 接口隔离原则:本单元中,由于没有此类需求,所以没有考虑接口隔离原则。
基于度量的架构分析
由于前两次作业都比较简单,代码量也较少,故在这里以第三次的代码为准进行架构分析。
可以看到,基本复杂度最高的类的复杂度也尚处于可接受水平,说明本次作业架构优化得当。
bug 分析
本单元的 bug 分析依然采取了随机生成数据并检测的策略。使用 Java 的 ClassLoader 功能直接将待测类加载到测试器的类路径中,然后直接在测试器中调用待测程序的 Main 函数。随机生成输入数据,并模拟标准读入的接口传递数据。最终的程序 bug 都成功在调试期间发现,而强测和互测中没有出现 bug。
在互测中阅读他人的代码时,重点寻找了死锁出现的条件和情况。不过很遗憾,在互测中并没有发现他人的 bug。
心得体会
本单元OO作业让我对多线程操作的熟练程度进一步提高,并且对电梯的调度算法有了初步的认识,总的来说还是收获较大。